Merge remote-tracking branch 'origin/development' into remove-grain-growth
This commit is contained in:
commit
63465f4d27
|
@ -9,7 +9,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ['3.7', '3.8', '3.9'] #, '3.10']
|
python-version: ['3.8', '3.9'] #, '3.10']
|
||||||
os: [ubuntu-latest, macos-latest]
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -46,7 +46,7 @@ variables:
|
||||||
# ++++++++++++ PETSc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
# ++++++++++++ PETSc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
PETSC_GNU: "Libraries/PETSc/3.16.1/GNU-10-OpenMPI-4.1.1"
|
PETSC_GNU: "Libraries/PETSc/3.16.1/GNU-10-OpenMPI-4.1.1"
|
||||||
PETSC_INTELLLVM: "Libraries/PETSc/3.16.3/oneAPI-2022.0.1-IntelMPI-2021.5.0"
|
PETSC_INTELLLVM: "Libraries/PETSc/3.16.3/oneAPI-2022.0.1-IntelMPI-2021.5.0"
|
||||||
PETSC_INTEL: "Libraries/PETSc/3.16.2/Intel-2022.0.1-IntelMPI-2021.5.0"
|
PETSC_INTEL: "Libraries/PETSc/3.16.3/Intel-2022.0.1-IntelMPI-2021.5.0"
|
||||||
# ++++++++++++ MSC Marc +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
# ++++++++++++ MSC Marc +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
MSC: "FEM/MSC/2021.3.1"
|
MSC: "FEM/MSC/2021.3.1"
|
||||||
IntelMarc: "Compiler/Intel/19.1.2 Libraries/IMKL/2020"
|
IntelMarc: "Compiler/Intel/19.1.2 Libraries/IMKL/2020"
|
||||||
|
@ -79,49 +79,69 @@ mypy:
|
||||||
|
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
test_grid_GNU:
|
grid_GNU:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
- module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU}
|
- module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU}
|
||||||
- cd PRIVATE/testing/pytest
|
- cd PRIVATE/testing/pytest
|
||||||
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_GNU
|
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_GNU
|
||||||
|
|
||||||
test_mesh_GNU:
|
mesh_GNU:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
- module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU}
|
- module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU}
|
||||||
- cd PRIVATE/testing/pytest
|
- cd PRIVATE/testing/pytest
|
||||||
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_GNU
|
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_GNU
|
||||||
|
|
||||||
test_mesh_IntelLLVM:
|
grid_GNU-64bit:
|
||||||
|
stage: compile
|
||||||
|
script:
|
||||||
|
- module load Compiler/GNU/10 Libraries/PETSc/3.16.2/64bit
|
||||||
|
- cd PRIVATE/testing/pytest
|
||||||
|
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_GNU-64bit
|
||||||
|
|
||||||
|
mesh_GNU-64bit:
|
||||||
|
stage: compile
|
||||||
|
script:
|
||||||
|
- module load Compiler/GNU/10 Libraries/PETSc/3.16.2/64bit
|
||||||
|
- cd PRIVATE/testing/pytest
|
||||||
|
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_GNU-64bit
|
||||||
|
|
||||||
|
grid_IntelLLVM:
|
||||||
|
stage: compile
|
||||||
|
script:
|
||||||
|
- module load ${COMPILER_INTELLLVM} ${MPI_INTELLLVM} ${PETSC_INTELLLVM}
|
||||||
|
- cd PRIVATE/testing/pytest
|
||||||
|
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_IntelLLVM
|
||||||
|
|
||||||
|
mesh_IntelLLVM:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
- module load ${COMPILER_INTELLLVM} ${MPI_INTELLLVM} ${PETSC_INTELLLVM}
|
- module load ${COMPILER_INTELLLVM} ${MPI_INTELLLVM} ${PETSC_INTELLLVM}
|
||||||
- cd PRIVATE/testing/pytest
|
- cd PRIVATE/testing/pytest
|
||||||
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_IntelLLVM
|
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_IntelLLVM
|
||||||
|
|
||||||
test_grid_Intel:
|
grid_Intel:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
|
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
|
||||||
- cd PRIVATE/testing/pytest
|
- cd PRIVATE/testing/pytest
|
||||||
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_Intel
|
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_Intel
|
||||||
|
|
||||||
test_mesh_Intel:
|
mesh_Intel:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
|
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
|
||||||
- cd PRIVATE/testing/pytest
|
- cd PRIVATE/testing/pytest
|
||||||
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_Intel
|
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_Intel
|
||||||
|
|
||||||
test_Marc:
|
Marc_Intel:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
- module load $IntelMarc $HDF5Marc $MSC
|
- module load $IntelMarc $HDF5Marc $MSC
|
||||||
- cd PRIVATE/testing/pytest
|
- cd PRIVATE/testing/pytest
|
||||||
- pytest -k 'compile and Marc' --basetemp ${TESTROOT}/compile_Marc
|
- pytest -k 'compile and Marc' --basetemp ${TESTROOT}/compile_Marc
|
||||||
|
|
||||||
|
|
||||||
setup_grid:
|
setup_grid:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
|
@ -138,7 +158,7 @@ setup_mesh:
|
||||||
- cmake -DDAMASK_SOLVER=MESH -DCMAKE_INSTALL_PREFIX=${TESTROOT} ${CI_PROJECT_DIR}
|
- cmake -DDAMASK_SOLVER=MESH -DCMAKE_INSTALL_PREFIX=${TESTROOT} ${CI_PROJECT_DIR}
|
||||||
- make -j2 all install
|
- make -j2 all install
|
||||||
|
|
||||||
compile_Marc:
|
setup_Marc:
|
||||||
stage: compile
|
stage: compile
|
||||||
script:
|
script:
|
||||||
- module load $IntelMarc $HDF5Marc $MSC
|
- module load $IntelMarc $HDF5Marc $MSC
|
||||||
|
@ -172,6 +192,10 @@ Marc:
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
grid_runtime:
|
grid_runtime:
|
||||||
stage: performance
|
stage: performance
|
||||||
|
before_script:
|
||||||
|
- ${LOCAL_HOME}/bin/queue ${CI_JOB_ID} --blocking
|
||||||
|
- source env/DAMASK.sh
|
||||||
|
- echo Job start:" $(date)"
|
||||||
script:
|
script:
|
||||||
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
|
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
|
||||||
- cd $(mktemp -d)
|
- cd $(mktemp -d)
|
||||||
|
@ -186,10 +210,6 @@ grid_runtime:
|
||||||
--output_dir ./
|
--output_dir ./
|
||||||
--tag ${CI_COMMIT_SHA}
|
--tag ${CI_COMMIT_SHA}
|
||||||
- if [ ${CI_COMMIT_BRANCH} == development ]; then git commit -am ${CI_PIPELINE_ID}_${CI_COMMIT_SHA}; git push; fi
|
- if [ ${CI_COMMIT_BRANCH} == development ]; then git commit -am ${CI_PIPELINE_ID}_${CI_COMMIT_SHA}; git push; fi
|
||||||
before_script:
|
|
||||||
- ${LOCAL_HOME}/bin/queue ${CI_JOB_ID} --blocking
|
|
||||||
- source env/DAMASK.sh
|
|
||||||
- echo Job start:" $(date)"
|
|
||||||
|
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
@ -209,19 +229,10 @@ update_revision:
|
||||||
script:
|
script:
|
||||||
- cd $(mktemp -d)
|
- cd $(mktemp -d)
|
||||||
- git clone -q git@git.damask.mpie.de:damask/DAMASK.git .
|
- git clone -q git@git.damask.mpie.de:damask/DAMASK.git .
|
||||||
- git checkout ${CI_COMMIT_SHA}
|
- git pull
|
||||||
- export VERSION=$(git describe)
|
- export VERSION=$(git describe ${CI_COMMIT_SHA})
|
||||||
- echo ${VERSION} > python/damask/VERSION
|
- echo ${VERSION} > python/damask/VERSION
|
||||||
- git add python/damask/VERSION
|
- git commit python/damask/VERSION -m "[skip ci] updated version information after successful test of $VERSION"
|
||||||
- git commit -m "[skip ci] updated version information after successful test of $VERSION"
|
- if [ ${CI_COMMIT_SHA} == $(git rev-parse HEAD^) ]; then git push origin HEAD:master HEAD:development; fi
|
||||||
- export UPDATEDREV=$(git describe) # tested state + 1 commit
|
|
||||||
- git checkout master
|
|
||||||
- git pull
|
|
||||||
- git merge $UPDATEDREV -s recursive -X ours # conflicts occur only for inconsistent state
|
|
||||||
- git push
|
|
||||||
- git checkout development
|
|
||||||
- git pull
|
|
||||||
- git merge master -s recursive -X ours -m "[skip ci] Merge branch 'master' into development" # only possible conflict is in VERSION file
|
|
||||||
- git push origin development # development is unchanged (as master is based on it) but has updated VERSION file
|
|
||||||
only:
|
only:
|
||||||
- development
|
- development
|
||||||
|
|
110
COPYING
110
COPYING
|
@ -1,23 +1,21 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
software and other kinds of works.
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
The licenses for most software and other practical works are designed
|
||||||
to take away your freedom to share and change the works. By contrast,
|
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
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
share and change all versions of a program--to make sure it remains free
|
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
|
software for all its users.
|
||||||
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
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
@ -26,44 +24,34 @@ 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
|
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.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
Developers that use our General Public Licenses protect your rights
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
you this License which gives you legal permission to copy, distribute
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
and/or modify the software.
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
A secondary benefit of defending all users' freedom is that
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
improvements made in alternate versions of the program, if they
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
receive widespread use, become available for other developers to
|
||||||
or can get the source code. And you must show them these terms so they
|
incorporate. Many developers of free software are heartened and
|
||||||
know their rights.
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
The GNU Affero General Public License is designed specifically to
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
ensure that, in such cases, the modified source code becomes available
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
An older license, called the Affero General Public License and
|
||||||
that there is no warranty for this free software. For both users' and
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
changed, so that their problems will not be attributed erroneously to
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
authors of previous versions.
|
this license.
|
||||||
|
|
||||||
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
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
|
@ -72,7 +60,7 @@ modification follow.
|
||||||
|
|
||||||
0. Definitions.
|
0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
works, such as semiconductor masks.
|
works, such as semiconductor masks.
|
||||||
|
@ -549,35 +537,45 @@ 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
|
the Program, the only way you could satisfy both those terms and this
|
||||||
License would be to refrain entirely from conveying the Program.
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
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
|
under version 3 of the GNU General Public License into a single
|
||||||
combined work, and to convey the resulting work. The terms of this
|
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,
|
License will continue to apply to the part which is the covered work,
|
||||||
but the special requirements of the GNU Affero General Public License,
|
but the work with which it is combined will remain governed by version
|
||||||
section 13, concerning interaction through a network will apply to the
|
3 of the GNU General Public License.
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
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
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Program specifies that a certain numbered version of the GNU General
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
Public License "or any later version" applies to it, you have the
|
Public License "or any later version" applies to it, you have the
|
||||||
option of following the terms and conditions either of that numbered
|
option of following the terms and conditions either of that numbered
|
||||||
version or of any later version published by the Free Software
|
version or of any later version published by the Free Software
|
||||||
Foundation. If the Program does not specify a version number of the
|
Foundation. If the Program does not specify a version number of the
|
||||||
GNU General Public License, you may choose any version ever published
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
by the Free Software Foundation.
|
by the Free Software Foundation.
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
If the Program specifies that a proxy can decide which future
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
public statement of acceptance of a version permanently authorizes you
|
public statement of acceptance of a version permanently authorizes you
|
||||||
to choose that version for the Program.
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
|
10
LICENSE
10
LICENSE
|
@ -1,14 +1,14 @@
|
||||||
Copyright 2011-2021 Max-Planck-Institut für Eisenforschung GmbH
|
Copyright 2011-2022 Max-Planck-Institut für Eisenforschung GmbH
|
||||||
|
|
||||||
DAMASK is free software: you can redistribute it and/or modify
|
DAMASK is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
2
PRIVATE
2
PRIVATE
|
@ -1 +1 @@
|
||||||
Subproject commit b898a8b5552bd9d1c555edc3d8134564dd32fe53
|
Subproject commit 5598ec4892b0921fccf63e8570f9fcd8e0365716
|
|
@ -6,7 +6,7 @@ references:
|
||||||
|
|
||||||
output: [xi_sl, xi_tw]
|
output: [xi_sl, xi_tw]
|
||||||
|
|
||||||
N_sl: [3, 3, 6, 0, 6] # basal, prism, -, 1. pyr<a>, -, 2. pyr<c+a>
|
N_sl: [3, 3, 6, 0, 6] # basal, prism, 1. pyr<a>, -, 2. pyr<c+a>
|
||||||
N_tw: [6, 0, 6] # tension, -, compression
|
N_tw: [6, 0, 6] # tension, -, compression
|
||||||
|
|
||||||
xi_0_sl: [10.e+6, 55.e+6, 60.e+6, 0., 60.e+6]
|
xi_0_sl: [10.e+6, 55.e+6, 60.e+6, 0., 60.e+6]
|
||||||
|
@ -23,9 +23,13 @@ f_sat_sl-tw: 10.0
|
||||||
h_0_sl-sl: 500.0e+6
|
h_0_sl-sl: 500.0e+6
|
||||||
h_0_tw-tw: 50.0e+6
|
h_0_tw-tw: 50.0e+6
|
||||||
h_0_tw-sl: 150.0e+6
|
h_0_tw-sl: 150.0e+6
|
||||||
h_sl-sl: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
h_sl-sl: [+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
||||||
1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,
|
+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
|
||||||
1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, +1.0, 1.0] # unused entries are indicated by -1.0
|
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,
|
||||||
|
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,
|
||||||
|
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0,
|
||||||
|
+1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0,
|
||||||
|
-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0] # unused entries are indicated by -1.0
|
||||||
h_tw-tw: [+1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0,
|
h_tw-tw: [+1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0,
|
||||||
-1.0, 1.0] # unused entries are indicated by -1.0
|
-1.0, 1.0] # unused entries are indicated by -1.0
|
||||||
h_tw-sl: [1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0,
|
h_tw-sl: [1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0,
|
||||||
|
|
|
@ -8,7 +8,7 @@ references:
|
||||||
https://doi.org/10.1016/j.actamat.2017.05.015
|
https://doi.org/10.1016/j.actamat.2017.05.015
|
||||||
output: [gamma_sl]
|
output: [gamma_sl]
|
||||||
|
|
||||||
N_sl: [3, 3, 0, 12] # basal, 1. prism, -, 1. pyr<c+a>
|
N_sl: [3, 3, 0, 12] # basal, prism, -, 1. pyr<c+a>
|
||||||
n_sl: 20
|
n_sl: 20
|
||||||
a_sl: 2.0
|
a_sl: 2.0
|
||||||
dot_gamma_0_sl: 0.001
|
dot_gamma_0_sl: 0.001
|
||||||
|
@ -20,5 +20,8 @@ xi_inf_sl: [568.e+6, 150.e+7, 0.0, 3420.e+6]
|
||||||
# L. Wang et al. :
|
# L. Wang et al. :
|
||||||
# xi_0_sl: [127.e+6, 96.e+6, 0.0, 240.e+6]
|
# xi_0_sl: [127.e+6, 96.e+6, 0.0, 240.e+6]
|
||||||
|
|
||||||
h_sl-sl: [+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0,
|
h_sl-sl: [+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0,
|
||||||
-1.0, -1.0, +1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0] # unused entries are indicated by -1.0
|
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,
|
||||||
|
+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
||||||
|
+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
||||||
|
+1.0, 1.0, 1.0, 1.0, 1.0, 1.0] # unused entries are indicated by -1.0
|
||||||
|
|
358
img/COPYING
358
img/COPYING
|
@ -1,94 +1,312 @@
|
||||||
Creative Commons Attribution-NoDerivatives 4.0 International Public License
|
Creative Commons Attribution-NoDerivatives 4.0 International Public
|
||||||
|
License
|
||||||
|
|
||||||
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-NoDerivatives 4.0 International Public License ("Public
|
||||||
|
License"). To the extent this Public License may be interpreted as a
|
||||||
|
contract, You are granted the Licensed Rights in consideration of Your
|
||||||
|
acceptance of these terms and conditions, and the Licensor grants You
|
||||||
|
such rights in consideration of benefits the Licensor receives from
|
||||||
|
making the Licensed Material available under these terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
Section 1 – Definitions.
|
|
||||||
|
|
||||||
Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
|
Section 1 -- Definitions.
|
||||||
Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
|
|
||||||
Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
|
|
||||||
Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
|
|
||||||
Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
|
|
||||||
Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
|
|
||||||
Licensor means the individual(s) or entity(ies) granting rights under this Public License.
|
|
||||||
Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
|
|
||||||
Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
|
|
||||||
You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
|
|
||||||
|
|
||||||
Section 2 – Scope.
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
License grant.
|
b. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
|
closely related to copyright including, without limitation,
|
||||||
reproduce and Share the Licensed Material, in whole or in part; and
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
produce and reproduce, but not Share, Adapted Material.
|
Rights, without regard to how the rights are labeled or
|
||||||
Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
|
categorized. For purposes of this Public License, the rights
|
||||||
Term. The term of this Public License is specified in Section 6(a).
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
|
Rights.
|
||||||
Downstream recipients.
|
|
||||||
Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
|
|
||||||
No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
|
|
||||||
No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
|
|
||||||
|
|
||||||
Other rights.
|
c. Effective Technological Measures means those measures that, in the
|
||||||
Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
|
absence of proper authority, may not be circumvented under laws
|
||||||
Patent and trademark rights are not licensed under this Public License.
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
Section 3 – License Conditions.
|
d. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
|
e. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
Attribution.
|
f. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
If You Share the Licensed Material, You must:
|
g. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
retain the following if it is supplied by the Licensor with the Licensed Material:
|
under this Public License.
|
||||||
identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
|
|
||||||
a copyright notice;
|
|
||||||
a notice that refers to this Public License;
|
|
||||||
a notice that refers to the disclaimer of warranties;
|
|
||||||
a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
|
|
||||||
indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
|
|
||||||
indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
|
|
||||||
For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material.
|
|
||||||
You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
|
|
||||||
If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
|
|
||||||
|
|
||||||
Section 4 – Sui Generis Database Rights.
|
h. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
|
i. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database, provided You do not Share Adapted Material;
|
j. You means the individual or entity exercising the Licensed Rights
|
||||||
if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
|
under this Public License. Your has a corresponding meaning.
|
||||||
You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
|
|
||||||
|
|
||||||
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
|
|
||||||
|
|
||||||
Section 5 – Disclaimer of Warranties and Limitation of Liability.
|
Section 2 -- Scope.
|
||||||
|
|
||||||
Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
|
a. License grant.
|
||||||
To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
|
|
||||||
|
|
||||||
The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
Section 6 – Term and Termination.
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part; and
|
||||||
|
|
||||||
This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
|
b. produce and reproduce, but not Share, Adapted Material.
|
||||||
|
|
||||||
Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
upon express reinstatement by the Licensor.
|
License does not apply, and You do not need to comply with
|
||||||
For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
|
its terms and conditions.
|
||||||
For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
|
|
||||||
Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
|
|
||||||
|
|
||||||
Section 7 – Other Terms and Conditions.
|
3. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
|
4. Media and formats; technical modifications allowed. The
|
||||||
Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
Section 8 – Interpretation.
|
5. Downstream recipients.
|
||||||
|
|
||||||
For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
|
recipient of the Licensed Material automatically
|
||||||
No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
|
receives an offer from the Licensor to exercise the
|
||||||
Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material, You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
For the avoidance of doubt, You do not have permission under
|
||||||
|
this Public License to Share Adapted Material.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database, provided You do not Share
|
||||||
|
Adapted Material;
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material; and
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
|
@ -12,17 +12,15 @@
|
||||||
|
|
||||||
# AEM
|
# AEM
|
||||||
if test "$MARCDLLOUTDIR" = ""; then
|
if test "$MARCDLLOUTDIR" = ""; then
|
||||||
@@ -390,8 +395,8 @@
|
@@ -390,7 +395,7 @@
|
||||||
I8DEFINES=
|
I8DEFINES=
|
||||||
I8CDEFINES=
|
I8CDEFINES=
|
||||||
else
|
else
|
||||||
- I8FFLAGS="-i8"
|
- I8FFLAGS="-i8"
|
||||||
- I8DEFINES="-DI64"
|
|
||||||
+ I8FFLAGS="-i8 -integer-size 64"
|
+ I8FFLAGS="-i8 -integer-size 64"
|
||||||
+ I8DEFINES="-DI64 -DINT=8"
|
I8DEFINES="-DI64"
|
||||||
I8CDEFINES="-U_DOUBLE -D_SINGLE"
|
I8CDEFINES="-U_DOUBLE -D_SINGLE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -498,7 +503,7 @@
|
@@ -498,7 +503,7 @@
|
||||||
PROFILE=" $PROFILE -pg"
|
PROFILE=" $PROFILE -pg"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -12,17 +12,15 @@
|
||||||
|
|
||||||
# AEM
|
# AEM
|
||||||
if test "$MARCDLLOUTDIR" = ""; then
|
if test "$MARCDLLOUTDIR" = ""; then
|
||||||
@@ -439,8 +444,8 @@
|
@@ -439,7 +444,7 @@
|
||||||
I8DEFINES=
|
I8DEFINES=
|
||||||
I8CDEFINES=
|
I8CDEFINES=
|
||||||
else
|
else
|
||||||
- I8FFLAGS="-i8"
|
- I8FFLAGS="-i8"
|
||||||
- I8DEFINES="-DI64"
|
|
||||||
+ I8FFLAGS="-i8 -integer-size 64"
|
+ I8FFLAGS="-i8 -integer-size 64"
|
||||||
+ I8DEFINES="-DI64 -DINT=8"
|
I8DEFINES="-DI64"
|
||||||
I8CDEFINES="-U_DOUBLE -D_SINGLE"
|
I8CDEFINES="-U_DOUBLE -D_SINGLE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -556,7 +561,7 @@
|
@@ -556,7 +561,7 @@
|
||||||
PROFILE=" $PROFILE -pg"
|
PROFILE=" $PROFILE -pg"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -12,17 +12,15 @@
|
||||||
# AEM
|
# AEM
|
||||||
if test "$MARCDLLOUTDIR" = ""; then
|
if test "$MARCDLLOUTDIR" = ""; then
|
||||||
DLLOUTDIR="$MARC_LIB"
|
DLLOUTDIR="$MARC_LIB"
|
||||||
@@ -439,8 +444,8 @@ if test "$MARC_INTEGER_SIZE" = "i4" ; then
|
@@ -439,7 +444,7 @@ if test "$MARC_INTEGER_SIZE" = "i4" ; then
|
||||||
I8DEFINES=
|
I8DEFINES=
|
||||||
I8CDEFINES=
|
I8CDEFINES=
|
||||||
else
|
else
|
||||||
- I8FFLAGS="-i8"
|
- I8FFLAGS="-i8"
|
||||||
- I8DEFINES="-DI64"
|
|
||||||
+ I8FFLAGS="-i8 -integer-size 64"
|
+ I8FFLAGS="-i8 -integer-size 64"
|
||||||
+ I8DEFINES="-DI64 -DINT=8"
|
I8DEFINES="-DI64"
|
||||||
I8CDEFINES="-U_DOUBLE -D_SINGLE"
|
I8CDEFINES="-U_DOUBLE -D_SINGLE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -556,7 +561,7 @@ then
|
@@ -556,7 +561,7 @@ then
|
||||||
PROFILE=" $PROFILE -pg"
|
PROFILE=" $PROFILE -pg"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
v3.0.0-alpha5-375-g76fe2d2b3
|
v3.0.0-alpha5-545-gad74f5dbe
|
||||||
|
|
|
@ -8,6 +8,7 @@ with open(_Path(__file__).parent/_Path('VERSION')) as _f:
|
||||||
version = _re.sub(r'^v','',_f.readline().strip())
|
version = _re.sub(r'^v','',_f.readline().strip())
|
||||||
__version__ = version
|
__version__ = version
|
||||||
|
|
||||||
|
from . import _typehints # noqa
|
||||||
from . import util # noqa
|
from . import util # noqa
|
||||||
from . import seeds # noqa
|
from . import seeds # noqa
|
||||||
from . import tensor # noqa
|
from . import tensor # noqa
|
||||||
|
@ -20,8 +21,8 @@ from ._rotation import Rotation # noqa
|
||||||
from ._crystal import Crystal # noqa
|
from ._crystal import Crystal # noqa
|
||||||
from ._orientation import Orientation # noqa
|
from ._orientation import Orientation # noqa
|
||||||
from ._table import Table # noqa
|
from ._table import Table # noqa
|
||||||
from ._vtk import VTK # noqa
|
|
||||||
from ._colormap import Colormap # noqa
|
from ._colormap import Colormap # noqa
|
||||||
|
from ._vtk import VTK # noqa
|
||||||
from ._config import Config # noqa
|
from ._config import Config # noqa
|
||||||
from ._configmaterial import ConfigMaterial # noqa
|
from ._configmaterial import ConfigMaterial # noqa
|
||||||
from ._grid import Grid # noqa
|
from ._grid import Grid # noqa
|
||||||
|
|
|
@ -3,13 +3,9 @@ import json
|
||||||
import functools
|
import functools
|
||||||
import colorsys
|
import colorsys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Sequence, Union, TextIO
|
from typing import Union, TextIO
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
try:
|
|
||||||
from numpy.typing import ArrayLike
|
|
||||||
except ImportError:
|
|
||||||
ArrayLike = Union[np.ndarray,Sequence[float]] # type: ignore
|
|
||||||
import scipy.interpolate as interp
|
import scipy.interpolate as interp
|
||||||
import matplotlib as mpl
|
import matplotlib as mpl
|
||||||
if os.name == 'posix' and 'DISPLAY' not in os.environ:
|
if os.name == 'posix' and 'DISPLAY' not in os.environ:
|
||||||
|
@ -18,6 +14,7 @@ import matplotlib.pyplot as plt
|
||||||
from matplotlib import cm
|
from matplotlib import cm
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from ._typehints import FloatSequence, FileHandle
|
||||||
from . import util
|
from . import util
|
||||||
from . import Table
|
from . import Table
|
||||||
|
|
||||||
|
@ -50,22 +47,35 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __eq__(self, other: object) -> bool:
|
def __eq__(self,
|
||||||
|
other: object) -> bool:
|
||||||
"""Test equality of colormaps."""
|
"""Test equality of colormaps."""
|
||||||
if not isinstance(other, Colormap):
|
if not isinstance(other, Colormap):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return len(self.colors) == len(other.colors) \
|
return len(self.colors) == len(other.colors) \
|
||||||
and bool(np.all(self.colors == other.colors))
|
and bool(np.all(self.colors == other.colors))
|
||||||
|
|
||||||
def __add__(self, other: 'Colormap') -> 'Colormap':
|
def __add__(self,
|
||||||
|
other: 'Colormap') -> 'Colormap':
|
||||||
"""Concatenate."""
|
"""Concatenate."""
|
||||||
return Colormap(np.vstack((self.colors,other.colors)),
|
return Colormap(np.vstack((self.colors,other.colors)),
|
||||||
f'{self.name}+{other.name}')
|
f'{self.name}+{other.name}')
|
||||||
|
|
||||||
def __iadd__(self, other: 'Colormap') -> 'Colormap':
|
def __iadd__(self,
|
||||||
|
other: 'Colormap') -> 'Colormap':
|
||||||
"""Concatenate (in-place)."""
|
"""Concatenate (in-place)."""
|
||||||
return self.__add__(other)
|
return self.__add__(other)
|
||||||
|
|
||||||
|
def __mul__(self,
|
||||||
|
factor: int) -> 'Colormap':
|
||||||
|
"""Repeat."""
|
||||||
|
return Colormap(np.vstack([self.colors]*factor),f'{self.name}*{factor}')
|
||||||
|
|
||||||
|
def __imul__(self,
|
||||||
|
factor: int) -> 'Colormap':
|
||||||
|
"""Repeat (in-place)."""
|
||||||
|
return self.__mul__(factor)
|
||||||
|
|
||||||
def __invert__(self) -> 'Colormap':
|
def __invert__(self) -> 'Colormap':
|
||||||
"""Reverse."""
|
"""Reverse."""
|
||||||
return self.reversed()
|
return self.reversed()
|
||||||
|
@ -82,8 +92,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_range(low: ArrayLike,
|
def from_range(low: FloatSequence,
|
||||||
high: ArrayLike,
|
high: FloatSequence,
|
||||||
name: str = 'DAMASK colormap',
|
name: str = 'DAMASK colormap',
|
||||||
N: int = 256,
|
N: int = 256,
|
||||||
model: str = 'rgb') -> 'Colormap':
|
model: str = 'rgb') -> 'Colormap':
|
||||||
|
@ -156,7 +166,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_predefined(name: str, N: int = 256) -> 'Colormap':
|
def from_predefined(name: str,
|
||||||
|
N: int = 256) -> 'Colormap':
|
||||||
"""
|
"""
|
||||||
Select from a set of predefined colormaps.
|
Select from a set of predefined colormaps.
|
||||||
|
|
||||||
|
@ -197,7 +208,7 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
|
|
||||||
def at(self,
|
def at(self,
|
||||||
fraction : Union[float,Sequence[float]]) -> np.ndarray:
|
fraction : Union[float,FloatSequence]) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Interpolate color at fraction.
|
Interpolate color at fraction.
|
||||||
|
|
||||||
|
@ -208,7 +219,7 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
color : np.ndarray, shape(...,4)
|
color : numpy.ndarray, shape(...,4)
|
||||||
RGBA values of interpolated color(s).
|
RGBA values of interpolated color(s).
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
|
@ -229,7 +240,7 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
def shade(self,
|
def shade(self,
|
||||||
field: np.ndarray,
|
field: np.ndarray,
|
||||||
bounds: ArrayLike = None,
|
bounds: FloatSequence = None,
|
||||||
gap: float = None) -> Image:
|
gap: float = None) -> Image:
|
||||||
"""
|
"""
|
||||||
Generate PIL image of 2D field using colormap.
|
Generate PIL image of 2D field using colormap.
|
||||||
|
@ -253,12 +264,10 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
np.logical_or (np.isnan(field), field == gap)) # mask NaN (and gap if present)
|
np.logical_or (np.isnan(field), field == gap)) # mask NaN (and gap if present)
|
||||||
|
|
||||||
l,r = (field[mask].min(),field[mask].max()) if bounds is None else \
|
l,r = (field[mask].min(),field[mask].max()) if bounds is None else \
|
||||||
np.array(bounds,float)[:2]
|
(bounds[0],bounds[1])
|
||||||
|
|
||||||
delta,avg = r-l,0.5*abs(r+l)
|
if abs(delta := r-l) * 1e8 <= (avg := 0.5*abs(r+l)): # delta is similar to numerical noise
|
||||||
|
l,r = (l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta)) # extend range to have actual data centered within
|
||||||
if abs(delta) * 1e8 <= avg: # delta is similar to numerical noise
|
|
||||||
l,r = l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta), # extend range to have actual data centered within
|
|
||||||
|
|
||||||
return Image.fromarray(
|
return Image.fromarray(
|
||||||
(np.dstack((
|
(np.dstack((
|
||||||
|
@ -270,7 +279,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
mode='RGBA')
|
mode='RGBA')
|
||||||
|
|
||||||
|
|
||||||
def reversed(self, name: str = None) -> 'Colormap':
|
def reversed(self,
|
||||||
|
name: str = None) -> 'Colormap':
|
||||||
"""
|
"""
|
||||||
Reverse.
|
Reverse.
|
||||||
|
|
||||||
|
@ -291,12 +301,12 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
>>> damask.Colormap.from_predefined('stress').reversed()
|
>>> damask.Colormap.from_predefined('stress').reversed()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
rev = super(Colormap,self).reversed(name)
|
rev = super().reversed(name)
|
||||||
return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name)
|
return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name)
|
||||||
|
|
||||||
|
|
||||||
def _get_file_handle(self,
|
def _get_file_handle(self,
|
||||||
fname: Union[TextIO, str, Path, None],
|
fname: Union[FileHandle, None],
|
||||||
suffix: str = '') -> TextIO:
|
suffix: str = '') -> TextIO:
|
||||||
"""
|
"""
|
||||||
Provide file handle.
|
Provide file handle.
|
||||||
|
@ -323,7 +333,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
return fname
|
return fname
|
||||||
|
|
||||||
|
|
||||||
def save_paraview(self, fname: Union[TextIO, str, Path] = None):
|
def save_paraview(self,
|
||||||
|
fname: FileHandle = None):
|
||||||
"""
|
"""
|
||||||
Save as JSON file for use in Paraview.
|
Save as JSON file for use in Paraview.
|
||||||
|
|
||||||
|
@ -350,7 +361,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
fhandle.write('\n')
|
fhandle.write('\n')
|
||||||
|
|
||||||
|
|
||||||
def save_ASCII(self, fname: Union[TextIO, str, Path] = None):
|
def save_ASCII(self,
|
||||||
|
fname: FileHandle = None):
|
||||||
"""
|
"""
|
||||||
Save as ASCII file.
|
Save as ASCII file.
|
||||||
|
|
||||||
|
@ -365,7 +377,7 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
t.save(self._get_file_handle(fname,'.txt'))
|
t.save(self._get_file_handle(fname,'.txt'))
|
||||||
|
|
||||||
|
|
||||||
def save_GOM(self, fname: Union[TextIO, str, Path] = None):
|
def save_GOM(self, fname: FileHandle = None):
|
||||||
"""
|
"""
|
||||||
Save as ASCII file for use in GOM Aramis.
|
Save as ASCII file for use in GOM Aramis.
|
||||||
|
|
||||||
|
@ -385,7 +397,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
self._get_file_handle(fname,'.legend').write(GOM_str)
|
self._get_file_handle(fname,'.legend').write(GOM_str)
|
||||||
|
|
||||||
|
|
||||||
def save_gmsh(self, fname: Union[TextIO, str, Path] = None):
|
def save_gmsh(self,
|
||||||
|
fname: FileHandle = None):
|
||||||
"""
|
"""
|
||||||
Save as ASCII file for use in gmsh.
|
Save as ASCII file for use in gmsh.
|
||||||
|
|
||||||
|
@ -424,7 +437,7 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
"""If saturation of one of the two colors is much less than the other, hue of the less."""
|
"""If saturation of one of the two colors is much less than the other, hue of the less."""
|
||||||
if msh_sat[0] >= msh_unsat[0]:
|
if msh_sat[0] >= msh_unsat[0]:
|
||||||
return msh_sat[2]
|
return msh_sat[2]
|
||||||
else:
|
|
||||||
hSpin = msh_sat[1]/np.sin(msh_sat[1])*np.sqrt(msh_unsat[0]**2.0-msh_sat[0]**2)/msh_sat[0]
|
hSpin = msh_sat[1]/np.sin(msh_sat[1])*np.sqrt(msh_unsat[0]**2.0-msh_sat[0]**2)/msh_sat[0]
|
||||||
if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
|
if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
|
||||||
return msh_sat[2] + hSpin
|
return msh_sat[2] + hSpin
|
||||||
|
@ -440,9 +453,9 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
else:
|
else:
|
||||||
lo = np.array([M_mid,0.0,0.0])
|
lo = np.array([M_mid,0.0,0.0])
|
||||||
frac = 2.0*frac - 1.0
|
frac = 2.0*frac - 1.0
|
||||||
if lo[1] < 0.05 and hi[1] > 0.05:
|
if lo[1] < 0.05 < hi[1]:
|
||||||
lo[2] = adjust_hue(hi,lo)
|
lo[2] = adjust_hue(hi,lo)
|
||||||
elif lo[1] > 0.05 and hi[1] < 0.05:
|
elif hi[1] < 0.05 < lo[1]:
|
||||||
hi[2] = adjust_hue(lo,hi)
|
hi[2] = adjust_hue(lo,hi)
|
||||||
|
|
||||||
return (1.0 - frac) * lo + frac * hi
|
return (1.0 - frac) * lo + frac * hi
|
||||||
|
@ -471,7 +484,7 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
|
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
|
||||||
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']}
|
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']}
|
||||||
|
|
||||||
_predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431],
|
_predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431], # noqa
|
||||||
'high': [0.250980,0.007843,0.000000]},
|
'high': [0.250980,0.007843,0.000000]},
|
||||||
'strain': {'low': [0.941177,0.941177,0.870588],
|
'strain': {'low': [0.941177,0.941177,0.870588],
|
||||||
'high': [0.266667,0.266667,0.000000]},
|
'high': [0.266667,0.266667,0.000000]},
|
||||||
|
@ -616,7 +629,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _lab2xyz(lab: np.ndarray, ref_white: np.ndarray = _REF_WHITE) -> np.ndarray:
|
def _lab2xyz(lab: np.ndarray,
|
||||||
|
ref_white: np.ndarray = _REF_WHITE) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
CIE Lab to CIE Xyz.
|
CIE Lab to CIE Xyz.
|
||||||
|
|
||||||
|
@ -647,7 +661,8 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
])*ref_white
|
])*ref_white
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _xyz2lab(xyz: np.ndarray, ref_white: np.ndarray = _REF_WHITE) -> np.ndarray:
|
def _xyz2lab(xyz: np.ndarray,
|
||||||
|
ref_white: np.ndarray = _REF_WHITE) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
CIE Xyz to CIE Lab.
|
CIE Xyz to CIE Lab.
|
||||||
|
|
||||||
|
|
|
@ -2,25 +2,34 @@ import copy
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
import abc
|
import abc
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Union, Dict, Any, Type, TypeVar
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
from ._typehints import FileHandle
|
||||||
from . import Rotation
|
from . import Rotation
|
||||||
|
|
||||||
|
MyType = TypeVar('MyType', bound='Config')
|
||||||
|
|
||||||
class NiceDumper(yaml.SafeDumper):
|
class NiceDumper(yaml.SafeDumper):
|
||||||
"""Make YAML readable for humans."""
|
"""Make YAML readable for humans."""
|
||||||
|
|
||||||
def write_line_break(self, data=None):
|
def write_line_break(self,
|
||||||
|
data: str = None):
|
||||||
super().write_line_break(data)
|
super().write_line_break(data)
|
||||||
|
|
||||||
if len(self.indents) == 1:
|
if len(self.indents) == 1:
|
||||||
super().write_line_break()
|
super().write_line_break()
|
||||||
|
|
||||||
def increase_indent(self, flow=False, indentless=False):
|
def increase_indent(self,
|
||||||
|
flow: bool = False,
|
||||||
|
indentless: bool = False):
|
||||||
return super().increase_indent(flow, False)
|
return super().increase_indent(flow, False)
|
||||||
|
|
||||||
def represent_data(self, data):
|
def represent_data(self,
|
||||||
|
data: Any):
|
||||||
"""Cast Config objects and its subclasses to dict."""
|
"""Cast Config objects and its subclasses to dict."""
|
||||||
if isinstance(data, dict) and type(data) != dict:
|
if isinstance(data, dict) and type(data) != dict:
|
||||||
return self.represent_data(dict(data))
|
return self.represent_data(dict(data))
|
||||||
|
@ -31,14 +40,17 @@ class NiceDumper(yaml.SafeDumper):
|
||||||
else:
|
else:
|
||||||
return super().represent_data(data)
|
return super().represent_data(data)
|
||||||
|
|
||||||
def ignore_aliases(self, data):
|
def ignore_aliases(self,
|
||||||
|
data: Any) -> bool:
|
||||||
"""Do not use references to existing objects."""
|
"""Do not use references to existing objects."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class Config(dict):
|
class Config(dict):
|
||||||
"""YAML-based configuration."""
|
"""YAML-based configuration."""
|
||||||
|
|
||||||
def __init__(self,yml=None,**kwargs):
|
def __init__(self,
|
||||||
|
yml: Union[str, Dict[str, Any]] = None,
|
||||||
|
**kwargs):
|
||||||
"""Initialize from YAML, dict, or key=value pairs."""
|
"""Initialize from YAML, dict, or key=value pairs."""
|
||||||
if isinstance(yml,str):
|
if isinstance(yml,str):
|
||||||
kwargs.update(yaml.safe_load(yml))
|
kwargs.update(yaml.safe_load(yml))
|
||||||
|
@ -47,7 +59,7 @@ class Config(dict):
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
"""Show as in file."""
|
"""Show as in file."""
|
||||||
output = StringIO()
|
output = StringIO()
|
||||||
self.save(output)
|
self.save(output)
|
||||||
|
@ -55,14 +67,15 @@ class Config(dict):
|
||||||
return ''.join(output.readlines())
|
return ''.join(output.readlines())
|
||||||
|
|
||||||
|
|
||||||
def __copy__(self):
|
def __copy__(self: MyType) -> MyType:
|
||||||
"""Create deep copy."""
|
"""Create deep copy."""
|
||||||
return copy.deepcopy(self)
|
return copy.deepcopy(self)
|
||||||
|
|
||||||
copy = __copy__
|
copy = __copy__
|
||||||
|
|
||||||
|
|
||||||
def __or__(self,other):
|
def __or__(self: MyType,
|
||||||
|
other) -> MyType:
|
||||||
"""
|
"""
|
||||||
Update configuration with contents of other.
|
Update configuration with contents of other.
|
||||||
|
|
||||||
|
@ -76,18 +89,24 @@ class Config(dict):
|
||||||
updated : damask.Config
|
updated : damask.Config
|
||||||
Updated configuration.
|
Updated configuration.
|
||||||
|
|
||||||
|
Note
|
||||||
|
----
|
||||||
|
This functionality is a backport for Python 3.8
|
||||||
|
|
||||||
"""
|
"""
|
||||||
duplicate = self.copy()
|
duplicate = self.copy()
|
||||||
duplicate.update(other)
|
duplicate.update(other)
|
||||||
return duplicate
|
return duplicate
|
||||||
|
|
||||||
|
|
||||||
def __ior__(self,other):
|
def __ior__(self: MyType,
|
||||||
|
other) -> MyType:
|
||||||
"""Update configuration with contents of other."""
|
"""Update configuration with contents of other."""
|
||||||
return self.__or__(other)
|
return self.__or__(other)
|
||||||
|
|
||||||
|
|
||||||
def delete(self,keys):
|
def delete(self: MyType,
|
||||||
|
keys: Union[Iterable, str]) -> MyType:
|
||||||
"""
|
"""
|
||||||
Remove configuration keys.
|
Remove configuration keys.
|
||||||
|
|
||||||
|
@ -109,7 +128,8 @@ class Config(dict):
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls,fname):
|
def load(cls: Type[MyType],
|
||||||
|
fname: FileHandle) -> MyType:
|
||||||
"""
|
"""
|
||||||
Load from yaml file.
|
Load from yaml file.
|
||||||
|
|
||||||
|
@ -124,14 +144,15 @@ class Config(dict):
|
||||||
Configuration from file.
|
Configuration from file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
if isinstance(fname, (str, Path)):
|
||||||
fhandle = open(fname)
|
fhandle = open(fname)
|
||||||
except TypeError:
|
else:
|
||||||
fhandle = fname
|
fhandle = fname
|
||||||
return cls(yaml.safe_load(fhandle))
|
return cls(yaml.safe_load(fhandle))
|
||||||
|
|
||||||
|
def save(self,
|
||||||
def save(self,fname,**kwargs):
|
fname: FileHandle,
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
Save to yaml file.
|
Save to yaml file.
|
||||||
|
|
||||||
|
@ -143,9 +164,9 @@ class Config(dict):
|
||||||
Keyword arguments parsed to yaml.dump.
|
Keyword arguments parsed to yaml.dump.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
if isinstance(fname, (str, Path)):
|
||||||
fhandle = open(fname,'w',newline='\n')
|
fhandle = open(fname,'w',newline='\n')
|
||||||
except TypeError:
|
else:
|
||||||
fhandle = fname
|
fhandle = fname
|
||||||
|
|
||||||
if 'width' not in kwargs:
|
if 'width' not in kwargs:
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import h5py
|
import h5py
|
||||||
|
from typing import Sequence, Dict, Any, Collection
|
||||||
|
|
||||||
|
from ._typehints import FileHandle
|
||||||
from . import Config
|
from . import Config
|
||||||
from . import Rotation
|
from . import Rotation
|
||||||
from . import Orientation
|
from . import Orientation
|
||||||
from . import util
|
from . import util
|
||||||
|
from . import Table
|
||||||
|
|
||||||
|
|
||||||
class ConfigMaterial(Config):
|
class ConfigMaterial(Config):
|
||||||
"""
|
"""
|
||||||
|
@ -17,7 +21,9 @@ class ConfigMaterial(Config):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,d=None,**kwargs):
|
def __init__(self,
|
||||||
|
d: Dict[str, Any] = None,
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
New material configuration.
|
New material configuration.
|
||||||
|
|
||||||
|
@ -30,6 +36,7 @@ class ConfigMaterial(Config):
|
||||||
Initial content specified as pairs of key=value.
|
Initial content specified as pairs of key=value.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
default: Collection
|
||||||
if d is None:
|
if d is None:
|
||||||
for section, default in {'material':[],'homogenization':{},'phase':{}}.items():
|
for section, default in {'material':[],'homogenization':{},'phase':{}}.items():
|
||||||
if section not in kwargs: kwargs.update({section:default})
|
if section not in kwargs: kwargs.update({section:default})
|
||||||
|
@ -37,7 +44,9 @@ class ConfigMaterial(Config):
|
||||||
super().__init__(d,**kwargs)
|
super().__init__(d,**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def save(self,fname='material.yaml',**kwargs):
|
def save(self,
|
||||||
|
fname: FileHandle = 'material.yaml',
|
||||||
|
**kwargs):
|
||||||
"""
|
"""
|
||||||
Save to yaml file.
|
Save to yaml file.
|
||||||
|
|
||||||
|
@ -53,7 +62,8 @@ class ConfigMaterial(Config):
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls,fname='material.yaml'):
|
def load(cls,
|
||||||
|
fname: FileHandle = 'material.yaml') -> 'ConfigMaterial':
|
||||||
"""
|
"""
|
||||||
Load from yaml file.
|
Load from yaml file.
|
||||||
|
|
||||||
|
@ -72,10 +82,14 @@ class ConfigMaterial(Config):
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_DREAM3D(fname,
|
def load_DREAM3D(fname: str,
|
||||||
grain_data=None,cell_data=None,cell_ensemble_data='CellEnsembleData',
|
grain_data: str = None,
|
||||||
phases='Phases',Euler_angles='EulerAngles',phase_names='PhaseName',
|
cell_data: str = None,
|
||||||
base_group=None):
|
cell_ensemble_data: str = 'CellEnsembleData',
|
||||||
|
phases: str = 'Phases',
|
||||||
|
Euler_angles: str = 'EulerAngles',
|
||||||
|
phase_names: str = 'PhaseName',
|
||||||
|
base_group: str = None) -> 'ConfigMaterial':
|
||||||
"""
|
"""
|
||||||
Load DREAM.3D (HDF5) file.
|
Load DREAM.3D (HDF5) file.
|
||||||
|
|
||||||
|
@ -154,7 +168,8 @@ class ConfigMaterial(Config):
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_table(table,**kwargs):
|
def from_table(table: Table,
|
||||||
|
**kwargs) -> 'ConfigMaterial':
|
||||||
"""
|
"""
|
||||||
Generate from an ASCII table.
|
Generate from an ASCII table.
|
||||||
|
|
||||||
|
@ -207,7 +222,7 @@ class ConfigMaterial(Config):
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_complete(self):
|
def is_complete(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Check for completeness.
|
Check for completeness.
|
||||||
|
|
||||||
|
@ -267,12 +282,11 @@ class ConfigMaterial(Config):
|
||||||
if homogenization - set(self['homogenization']):
|
if homogenization - set(self['homogenization']):
|
||||||
print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing')
|
print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing')
|
||||||
ok = False
|
ok = False
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_valid(self):
|
def is_valid(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Check for valid content.
|
Check for valid content.
|
||||||
|
|
||||||
|
@ -316,7 +330,10 @@ class ConfigMaterial(Config):
|
||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
|
||||||
def material_rename_phase(self,mapping,ID=None,constituent=None):
|
def material_rename_phase(self,
|
||||||
|
mapping: Dict[str, str],
|
||||||
|
ID: Sequence[int] = None,
|
||||||
|
constituent: Sequence[int] = None) -> 'ConfigMaterial':
|
||||||
"""
|
"""
|
||||||
Change phase name in material.
|
Change phase name in material.
|
||||||
|
|
||||||
|
@ -347,7 +364,9 @@ class ConfigMaterial(Config):
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def material_rename_homogenization(self,mapping,ID=None):
|
def material_rename_homogenization(self,
|
||||||
|
mapping: Dict[str, str],
|
||||||
|
ID: Sequence[int] = None) -> 'ConfigMaterial':
|
||||||
"""
|
"""
|
||||||
Change homogenization name in material.
|
Change homogenization name in material.
|
||||||
|
|
||||||
|
@ -374,7 +393,8 @@ class ConfigMaterial(Config):
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def material_add(self,**kwargs):
|
def material_add(self,
|
||||||
|
**kwargs: Any) -> 'ConfigMaterial':
|
||||||
"""
|
"""
|
||||||
Add material entries.
|
Add material entries.
|
||||||
|
|
||||||
|
@ -453,7 +473,7 @@ class ConfigMaterial(Config):
|
||||||
N = max(N,s[0]) if len(s)>0 else N
|
N = max(N,s[0]) if len(s)>0 else N
|
||||||
n = max(n,s[1]) if len(s)>1 else n
|
n = max(n,s[1]) if len(s)>1 else n
|
||||||
|
|
||||||
mat = [{'constituents':[{} for _ in range(n)]} for _ in range(N)]
|
mat: Sequence[dict] = [{'constituents':[{} for _ in range(n)]} for _ in range(N)]
|
||||||
|
|
||||||
if 'v' not in kwargs:
|
if 'v' not in kwargs:
|
||||||
shaped['v'] = np.broadcast_to(1/n,(N,n))
|
shaped['v'] = np.broadcast_to(1/n,(N,n))
|
||||||
|
|
|
@ -33,9 +33,9 @@ class Crystal():
|
||||||
def __init__(self,*,
|
def __init__(self,*,
|
||||||
family = None,
|
family = None,
|
||||||
lattice = None,
|
lattice = None,
|
||||||
a = None,b = None,c = None,
|
a: float = None, b: float = None, c: float = None,
|
||||||
alpha = None,beta = None,gamma = None,
|
alpha: float = None, beta: float = None, gamma: float = None,
|
||||||
degrees = False):
|
degrees: bool = False):
|
||||||
"""
|
"""
|
||||||
Representation of crystal in terms of crystal family or Bravais lattice.
|
Representation of crystal in terms of crystal family or Bravais lattice.
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class Crystal():
|
||||||
Angles are given in degrees. Defaults to False.
|
Angles are given in degrees. Defaults to False.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if family not in [None] + list(lattice_symmetries.values()):
|
if family is not None and family not in list(lattice_symmetries.values()):
|
||||||
raise KeyError(f'invalid crystal family "{family}"')
|
raise KeyError(f'invalid crystal family "{family}"')
|
||||||
if lattice is not None and family is not None and family != lattice_symmetries[lattice]:
|
if lattice is not None and family is not None and family != lattice_symmetries[lattice]:
|
||||||
raise KeyError(f'incompatible family "{family}" for lattice "{lattice}"')
|
raise KeyError(f'incompatible family "{family}" for lattice "{lattice}"')
|
||||||
|
@ -107,9 +107,6 @@ class Crystal():
|
||||||
if np.any([np.roll([self.alpha,self.beta,self.gamma],r)[0]
|
if np.any([np.roll([self.alpha,self.beta,self.gamma],r)[0]
|
||||||
>= np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]):
|
>= np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]):
|
||||||
raise ValueError ('each lattice angle must be less than sum of others')
|
raise ValueError ('each lattice angle must be less than sum of others')
|
||||||
else:
|
|
||||||
self.a = self.b = self.c = None
|
|
||||||
self.alpha = self.beta = self.gamma = None
|
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -122,7 +119,8 @@ class Crystal():
|
||||||
'α={:.5g}°, β={:.5g}°, γ={:.5g}°'.format(*np.degrees(self.parameters[3:]))])
|
'α={:.5g}°, β={:.5g}°, γ={:.5g}°'.format(*np.degrees(self.parameters[3:]))])
|
||||||
|
|
||||||
|
|
||||||
def __eq__(self,other):
|
def __eq__(self,
|
||||||
|
other: object) -> bool:
|
||||||
"""
|
"""
|
||||||
Equal to other.
|
Equal to other.
|
||||||
|
|
||||||
|
@ -132,6 +130,8 @@ class Crystal():
|
||||||
Crystal to check for equality.
|
Crystal to check for equality.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if not isinstance(other, Crystal):
|
||||||
|
return NotImplemented
|
||||||
return self.lattice == other.lattice and \
|
return self.lattice == other.lattice and \
|
||||||
self.parameters == other.parameters and \
|
self.parameters == other.parameters and \
|
||||||
self.family == other.family
|
self.family == other.family
|
||||||
|
@ -139,8 +139,7 @@ class Crystal():
|
||||||
@property
|
@property
|
||||||
def parameters(self):
|
def parameters(self):
|
||||||
"""Return lattice parameters a, b, c, alpha, beta, gamma."""
|
"""Return lattice parameters a, b, c, alpha, beta, gamma."""
|
||||||
return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma)
|
if hasattr(self,'a'): return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def immutable(self):
|
def immutable(self):
|
||||||
|
@ -269,7 +268,7 @@ class Crystal():
|
||||||
https://doi.org/10.1063/1.1661333
|
https://doi.org/10.1063/1.1661333
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if None in self.parameters:
|
if self.parameters is None:
|
||||||
raise KeyError('missing crystal lattice parameters')
|
raise KeyError('missing crystal lattice parameters')
|
||||||
return np.array([
|
return np.array([
|
||||||
[1,0,0],
|
[1,0,0],
|
||||||
|
@ -315,7 +314,9 @@ class Crystal():
|
||||||
+ _lattice_points.get(self.lattice if self.lattice == 'hP' else \
|
+ _lattice_points.get(self.lattice if self.lattice == 'hP' else \
|
||||||
self.lattice[-1],None),dtype=float)
|
self.lattice[-1],None),dtype=float)
|
||||||
|
|
||||||
def to_lattice(self, *, direction: np.ndarray = None, plane: np.ndarray = None) -> np.ndarray:
|
def to_lattice(self, *,
|
||||||
|
direction: np.ndarray = None,
|
||||||
|
plane: np.ndarray = None) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Calculate lattice vector corresponding to crystal frame direction or plane normal.
|
Calculate lattice vector corresponding to crystal frame direction or plane normal.
|
||||||
|
|
||||||
|
@ -339,7 +340,9 @@ class Crystal():
|
||||||
return np.einsum('il,...l',basis,axis)
|
return np.einsum('il,...l',basis,axis)
|
||||||
|
|
||||||
|
|
||||||
def to_frame(self, *, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray:
|
def to_frame(self, *,
|
||||||
|
uvw: np.ndarray = None,
|
||||||
|
hkl: np.ndarray = None) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Calculate crystal frame vector along lattice direction [uvw] or plane normal (hkl).
|
Calculate crystal frame vector along lattice direction [uvw] or plane normal (hkl).
|
||||||
|
|
||||||
|
@ -362,7 +365,8 @@ class Crystal():
|
||||||
return np.einsum('il,...l',basis,axis)
|
return np.einsum('il,...l',basis,axis)
|
||||||
|
|
||||||
|
|
||||||
def kinematics(self, mode: str) -> Dict[str, List[np.ndarray]]:
|
def kinematics(self,
|
||||||
|
mode: str) -> Dict[str, List[np.ndarray]]:
|
||||||
"""
|
"""
|
||||||
Return crystal kinematics systems.
|
Return crystal kinematics systems.
|
||||||
|
|
||||||
|
@ -621,7 +625,8 @@ class Crystal():
|
||||||
'plane': [m[:,3:6] for m in master]}
|
'plane': [m[:,3:6] for m in master]}
|
||||||
|
|
||||||
|
|
||||||
def relation_operations(self, model: str) -> Tuple[str, Rotation]:
|
def relation_operations(self,
|
||||||
|
model: str) -> Tuple[str, Rotation]:
|
||||||
"""
|
"""
|
||||||
Crystallographic orientation relationships for phase transformations.
|
Crystallographic orientation relationships for phase transformations.
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@ import copy
|
||||||
import warnings
|
import warnings
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
import typing
|
||||||
|
from typing import Union, Optional, TextIO, List, Sequence
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
@ -13,7 +16,8 @@ from . import VTK
|
||||||
from . import util
|
from . import util
|
||||||
from . import grid_filters
|
from . import grid_filters
|
||||||
from . import Rotation
|
from . import Rotation
|
||||||
|
from . import Table
|
||||||
|
from ._typehints import FloatSequence, IntSequence
|
||||||
|
|
||||||
class Grid:
|
class Grid:
|
||||||
"""
|
"""
|
||||||
|
@ -25,30 +29,34 @@ class Grid:
|
||||||
the physical size.
|
the physical size.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,material,size,origin=[0.0,0.0,0.0],comments=[]):
|
def __init__(self,
|
||||||
|
material: np.ndarray,
|
||||||
|
size: FloatSequence,
|
||||||
|
origin: FloatSequence = np.zeros(3),
|
||||||
|
comments: Union[str, Sequence[str]] = None):
|
||||||
"""
|
"""
|
||||||
New geometry definition for grid solvers.
|
New geometry definition for grid solvers.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
material : numpy.ndarray of shape (:,:,:)
|
material : numpy.ndarray, shape (:,:,:)
|
||||||
Material indices. The shape of the material array defines
|
Material indices. The shape of the material array defines
|
||||||
the number of cells.
|
the number of cells.
|
||||||
size : list or numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of grid in meter.
|
Physical size of grid in meter.
|
||||||
origin : list or numpy.ndarray of shape (3), optional
|
origin : sequence of float, len (3), optional
|
||||||
Coordinates of grid origin in meter.
|
Coordinates of grid origin in meter. Defaults to [0.0,0.0,0.0].
|
||||||
comments : list of str, optional
|
comments : (list of) str, optional
|
||||||
Comments, e.g. history of operations.
|
Comments, e.g. history of operations.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.material = material
|
self.material = material
|
||||||
self.size = size
|
self.size = size # type: ignore
|
||||||
self.origin = origin
|
self.origin = origin # type: ignore
|
||||||
self.comments = comments
|
self.comments = [] if comments is None else comments # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
"""Basic information on grid definition."""
|
"""Basic information on grid definition."""
|
||||||
mat_min = np.nanmin(self.material)
|
mat_min = np.nanmin(self.material)
|
||||||
mat_max = np.nanmax(self.material)
|
mat_max = np.nanmax(self.material)
|
||||||
|
@ -62,14 +70,15 @@ class Grid:
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def __copy__(self):
|
def __copy__(self) -> 'Grid':
|
||||||
"""Create deep copy."""
|
"""Create deep copy."""
|
||||||
return copy.deepcopy(self)
|
return copy.deepcopy(self)
|
||||||
|
|
||||||
copy = __copy__
|
copy = __copy__
|
||||||
|
|
||||||
|
|
||||||
def __eq__(self,other):
|
def __eq__(self,
|
||||||
|
other: object) -> bool:
|
||||||
"""
|
"""
|
||||||
Test equality of other.
|
Test equality of other.
|
||||||
|
|
||||||
|
@ -79,24 +88,27 @@ class Grid:
|
||||||
Grid to compare self against.
|
Grid to compare self against.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return (np.allclose(other.size,self.size)
|
if not isinstance(other, Grid):
|
||||||
|
return NotImplemented
|
||||||
|
return bool(np.allclose(other.size,self.size)
|
||||||
and np.allclose(other.origin,self.origin)
|
and np.allclose(other.origin,self.origin)
|
||||||
and np.all(other.cells == self.cells)
|
and np.all(other.cells == self.cells)
|
||||||
and np.all(other.material == self.material))
|
and np.all(other.material == self.material))
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def material(self):
|
def material(self) -> np.ndarray:
|
||||||
"""Material indices."""
|
"""Material indices."""
|
||||||
return self._material
|
return self._material
|
||||||
|
|
||||||
@material.setter
|
@material.setter
|
||||||
def material(self,material):
|
def material(self,
|
||||||
|
material: np.ndarray):
|
||||||
if len(material.shape) != 3:
|
if len(material.shape) != 3:
|
||||||
raise ValueError(f'invalid material shape {material.shape}')
|
raise ValueError(f'invalid material shape {material.shape}')
|
||||||
elif material.dtype not in np.sctypes['float'] + np.sctypes['int']:
|
if material.dtype not in np.sctypes['float'] and material.dtype not in np.sctypes['int']:
|
||||||
raise TypeError(f'invalid material data type {material.dtype}')
|
raise TypeError(f'invalid material data type {material.dtype}')
|
||||||
else:
|
|
||||||
self._material = np.copy(material)
|
self._material = np.copy(material)
|
||||||
|
|
||||||
if self.material.dtype in np.sctypes['float'] and \
|
if self.material.dtype in np.sctypes['float'] and \
|
||||||
|
@ -105,59 +117,62 @@ class Grid:
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self) -> np.ndarray:
|
||||||
"""Physical size of grid in meter."""
|
"""Physical size of grid in meter."""
|
||||||
return self._size
|
return self._size
|
||||||
|
|
||||||
@size.setter
|
@size.setter
|
||||||
def size(self,size):
|
def size(self,
|
||||||
|
size: FloatSequence):
|
||||||
if len(size) != 3 or any(np.array(size) < 0):
|
if len(size) != 3 or any(np.array(size) < 0):
|
||||||
raise ValueError(f'invalid size {size}')
|
raise ValueError(f'invalid size {size}')
|
||||||
else:
|
|
||||||
self._size = np.array(size)
|
self._size = np.array(size)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def origin(self):
|
def origin(self) -> np.ndarray:
|
||||||
"""Coordinates of grid origin in meter."""
|
"""Coordinates of grid origin in meter."""
|
||||||
return self._origin
|
return self._origin
|
||||||
|
|
||||||
@origin.setter
|
@origin.setter
|
||||||
def origin(self,origin):
|
def origin(self,
|
||||||
|
origin: FloatSequence):
|
||||||
if len(origin) != 3:
|
if len(origin) != 3:
|
||||||
raise ValueError(f'invalid origin {origin}')
|
raise ValueError(f'invalid origin {origin}')
|
||||||
else:
|
|
||||||
self._origin = np.array(origin)
|
self._origin = np.array(origin)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def comments(self):
|
def comments(self) -> List[str]:
|
||||||
"""Comments, e.g. history of operations."""
|
"""Comments, e.g. history of operations."""
|
||||||
return self._comments
|
return self._comments
|
||||||
|
|
||||||
@comments.setter
|
@comments.setter
|
||||||
def comments(self,comments):
|
def comments(self,
|
||||||
|
comments: Union[str, Sequence[str]]):
|
||||||
self._comments = [str(c) for c in comments] if isinstance(comments,list) else [str(comments)]
|
self._comments = [str(c) for c in comments] if isinstance(comments,list) else [str(comments)]
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cells(self):
|
def cells(self) -> np.ndarray:
|
||||||
"""Number of cells in x,y,z direction."""
|
"""Number of cells in x,y,z direction."""
|
||||||
return np.asarray(self.material.shape)
|
return np.asarray(self.material.shape)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def N_materials(self):
|
def N_materials(self) -> int:
|
||||||
"""Number of (unique) material indices within grid."""
|
"""Number of (unique) material indices within grid."""
|
||||||
return np.unique(self.material).size
|
return np.unique(self.material).size
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(fname):
|
def load(fname: Union[str, Path]) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Load from VTK image data file.
|
Load from VTK image data file.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
fname : str or or pathlib.Path
|
fname : str or pathlib.Path
|
||||||
Grid file to read. Valid extension is .vti, which will be appended
|
Grid file to read. Valid extension is .vti, which will be appended
|
||||||
if not given.
|
if not given.
|
||||||
|
|
||||||
|
@ -178,8 +193,9 @@ class Grid:
|
||||||
comments=comments)
|
comments=comments)
|
||||||
|
|
||||||
|
|
||||||
|
@typing. no_type_check
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_ASCII(fname):
|
def load_ASCII(fname)-> 'Grid':
|
||||||
"""
|
"""
|
||||||
Load from geom file.
|
Load from geom file.
|
||||||
|
|
||||||
|
@ -198,15 +214,17 @@ class Grid:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.0.0', DeprecationWarning,2)
|
warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.0.0', DeprecationWarning,2)
|
||||||
try:
|
if isinstance(fname, (str, Path)):
|
||||||
f = open(fname)
|
f = open(fname)
|
||||||
except TypeError:
|
elif isinstance(fname, TextIO):
|
||||||
f = fname
|
f = fname
|
||||||
|
else:
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
try:
|
try:
|
||||||
header_length,keyword = f.readline().split()[:2]
|
header_length_,keyword = f.readline().split()[:2]
|
||||||
header_length = int(header_length)
|
header_length = int(header_length_)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
header_length,keyword = (-1, 'invalid')
|
header_length,keyword = (-1, 'invalid')
|
||||||
if not keyword.startswith('head') or header_length < 3:
|
if not keyword.startswith('head') or header_length < 3:
|
||||||
|
@ -216,8 +234,7 @@ class Grid:
|
||||||
content = f.readlines()
|
content = f.readlines()
|
||||||
for i,line in enumerate(content[:header_length]):
|
for i,line in enumerate(content[:header_length]):
|
||||||
items = line.split('#')[0].lower().strip().split()
|
items = line.split('#')[0].lower().strip().split()
|
||||||
key = items[0] if items else ''
|
if (key := items[0] if items else '') == 'grid':
|
||||||
if key == 'grid':
|
|
||||||
cells = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']])
|
cells = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']])
|
||||||
elif key == 'size':
|
elif key == 'size':
|
||||||
size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']])
|
size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']])
|
||||||
|
@ -226,19 +243,18 @@ class Grid:
|
||||||
else:
|
else:
|
||||||
comments.append(line.strip())
|
comments.append(line.strip())
|
||||||
|
|
||||||
material = np.empty(cells.prod()) # initialize as flat array
|
material = np.empty(int(cells.prod())) # initialize as flat array
|
||||||
i = 0
|
i = 0
|
||||||
for line in content[header_length:]:
|
for line in content[header_length:]:
|
||||||
items = line.split('#')[0].split()
|
if len(items := line.split('#')[0].split()) == 3:
|
||||||
if len(items) == 3:
|
|
||||||
if items[1].lower() == 'of':
|
if items[1].lower() == 'of':
|
||||||
items = np.ones(int(items[0]))*float(items[2])
|
material_entry = np.ones(int(items[0]))*float(items[2])
|
||||||
elif items[1].lower() == 'to':
|
elif items[1].lower() == 'to':
|
||||||
items = np.linspace(int(items[0]),int(items[2]),
|
material_entry = np.linspace(int(items[0]),int(items[2]),
|
||||||
abs(int(items[2])-int(items[0]))+1,dtype=float)
|
abs(int(items[2])-int(items[0]))+1,dtype=float)
|
||||||
else: items = list(map(float,items))
|
else: material_entry = list(map(float, items))
|
||||||
else: items = list(map(float,items))
|
else: material_entry = list(map(float, items))
|
||||||
material[i:i+len(items)] = items
|
material[i:i+len(material_entry)] = material_entry
|
||||||
i += len(items)
|
i += len(items)
|
||||||
|
|
||||||
if i != cells.prod():
|
if i != cells.prod():
|
||||||
|
@ -251,13 +267,13 @@ class Grid:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_Neper(fname):
|
def load_Neper(fname: Union[str, Path]) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Load from Neper VTK file.
|
Load from Neper VTK file.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
fname : str, pathlib.Path, or file handle
|
fname : str or pathlib.Path
|
||||||
Geometry file to read.
|
Geometry file to read.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -266,7 +282,7 @@ class Grid:
|
||||||
Grid-based geometry from file.
|
Grid-based geometry from file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
v = VTK.load(fname,'vtkImageData')
|
v = VTK.load(fname,'ImageData')
|
||||||
cells = np.array(v.vtk_data.GetDimensions())-1
|
cells = np.array(v.vtk_data.GetDimensions())-1
|
||||||
bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T
|
bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T
|
||||||
|
|
||||||
|
@ -276,10 +292,10 @@ class Grid:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_DREAM3D(fname,
|
def load_DREAM3D(fname: Union[str, Path],
|
||||||
feature_IDs=None,cell_data=None,
|
feature_IDs: str = None, cell_data: str = None,
|
||||||
phases='Phases',Euler_angles='EulerAngles',
|
phases: str = 'Phases', Euler_angles: str = 'EulerAngles',
|
||||||
base_group=None):
|
base_group: str = None) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Load DREAM.3D (HDF5) file.
|
Load DREAM.3D (HDF5) file.
|
||||||
|
|
||||||
|
@ -290,24 +306,24 @@ class Grid:
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
fname : str
|
fname : str or or pathlib.Path
|
||||||
Filename of the DREAM.3D (HDF5) file.
|
Filename of the DREAM.3D (HDF5) file.
|
||||||
feature_IDs : str
|
feature_IDs : str, optional
|
||||||
Name of the dataset containing the mapping between cells and
|
Name of the dataset containing the mapping between cells and
|
||||||
grain-wise data. Defaults to 'None', in which case cell-wise
|
grain-wise data. Defaults to 'None', in which case cell-wise
|
||||||
data is used.
|
data is used.
|
||||||
cell_data : str
|
cell_data : str, optional
|
||||||
Name of the group (folder) containing cell-wise data. Defaults to
|
Name of the group (folder) containing cell-wise data. Defaults to
|
||||||
None in wich case it is automatically detected.
|
None in wich case it is automatically detected.
|
||||||
phases : str
|
phases : str, optional
|
||||||
Name of the dataset containing the phase ID. It is not used for
|
Name of the dataset containing the phase ID. It is not used for
|
||||||
grain-wise data, i.e. when feature_IDs is not None.
|
grain-wise data, i.e. when feature_IDs is not None.
|
||||||
Defaults to 'Phases'.
|
Defaults to 'Phases'.
|
||||||
Euler_angles : str
|
Euler_angles : str, optional
|
||||||
Name of the dataset containing the crystallographic orientation as
|
Name of the dataset containing the crystallographic orientation as
|
||||||
Euler angles in radians It is not used for grain-wise data, i.e.
|
Euler angles in radians It is not used for grain-wise data, i.e.
|
||||||
when feature_IDs is not None. Defaults to 'EulerAngles'.
|
when feature_IDs is not None. Defaults to 'EulerAngles'.
|
||||||
base_group : str
|
base_group : str, optional
|
||||||
Path to the group (folder) that contains geometry (_SIMPL_GEOMETRY),
|
Path to the group (folder) that contains geometry (_SIMPL_GEOMETRY),
|
||||||
and grain- or cell-wise data. Defaults to None, in which case
|
and grain- or cell-wise data. Defaults to None, in which case
|
||||||
it is set as the path that contains _SIMPL_GEOMETRY/SPACING.
|
it is set as the path that contains _SIMPL_GEOMETRY/SPACING.
|
||||||
|
@ -339,7 +355,9 @@ class Grid:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_table(table,coordinates,labels):
|
def from_table(table: Table,
|
||||||
|
coordinates: str,
|
||||||
|
labels: Union[str, Sequence[str]]) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Create grid from ASCII table.
|
Create grid from ASCII table.
|
||||||
|
|
||||||
|
@ -350,7 +368,7 @@ class Grid:
|
||||||
coordinates : str
|
coordinates : str
|
||||||
Label of the vector column containing the spatial coordinates.
|
Label of the vector column containing the spatial coordinates.
|
||||||
Need to be ordered (1./x fast, 3./z slow).
|
Need to be ordered (1./x fast, 3./z slow).
|
||||||
labels : str or list of str
|
labels : (list of) str
|
||||||
Label(s) of the columns containing the material definition.
|
Label(s) of the columns containing the material definition.
|
||||||
Each unique combination of values results in one material ID.
|
Each unique combination of values results in one material ID.
|
||||||
|
|
||||||
|
@ -372,28 +390,35 @@ class Grid:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _find_closest_seed(seeds, weights, point):
|
def _find_closest_seed(seeds: np.ndarray,
|
||||||
|
weights: np.ndarray,
|
||||||
|
point: np.ndarray) -> np.integer:
|
||||||
return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights)
|
return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_Laguerre_tessellation(cells,size,seeds,weights,material=None,periodic=True):
|
def from_Laguerre_tessellation(cells: IntSequence,
|
||||||
|
size: FloatSequence,
|
||||||
|
seeds: np.ndarray,
|
||||||
|
weights: FloatSequence,
|
||||||
|
material: IntSequence = None,
|
||||||
|
periodic: bool = True):
|
||||||
"""
|
"""
|
||||||
Create grid from Laguerre tessellation.
|
Create grid from Laguerre tessellation.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cells : int numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Number of cells in x,y,z direction.
|
Number of cells in x,y,z direction.
|
||||||
size : list or numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the grid in meter.
|
Physical size of the grid in meter.
|
||||||
seeds : numpy.ndarray of shape (:,3)
|
seeds : numpy.ndarray, shape (:,3)
|
||||||
Position of the seed points in meter. All points need to lay within the box.
|
Position of the seed points in meter. All points need to lay within the box.
|
||||||
weights : numpy.ndarray of shape (seeds.shape[0])
|
weights : sequence of float, len (seeds.shape[0])
|
||||||
Weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation.
|
Weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation.
|
||||||
material : numpy.ndarray of shape (seeds.shape[0]), optional
|
material : sequence of int, len (seeds.shape[0]), optional
|
||||||
Material ID of the seeds.
|
Material ID of the seeds.
|
||||||
Defaults to None, in which case materials are consecutively numbered.
|
Defaults to None, in which case materials are consecutively numbered.
|
||||||
periodic : Boolean, optional
|
periodic : bool, optional
|
||||||
Assume grid to be periodic. Defaults to True.
|
Assume grid to be periodic. Defaults to True.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -402,13 +427,14 @@ class Grid:
|
||||||
Grid-based geometry from tessellation.
|
Grid-based geometry from tessellation.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
weights_p: FloatSequence
|
||||||
if periodic:
|
if periodic:
|
||||||
weights_p = np.tile(weights,27) # Laguerre weights (1,2,3,1,2,3,...,1,2,3)
|
weights_p = np.tile(weights,27) # Laguerre weights (1,2,3,1,2,3,...,1,2,3)
|
||||||
seeds_p = np.vstack((seeds -np.array([size[0],0.,0.]),seeds, seeds +np.array([size[0],0.,0.])))
|
seeds_p = np.vstack((seeds -np.array([size[0],0.,0.]),seeds, seeds +np.array([size[0],0.,0.])))
|
||||||
seeds_p = np.vstack((seeds_p-np.array([0.,size[1],0.]),seeds_p,seeds_p+np.array([0.,size[1],0.])))
|
seeds_p = np.vstack((seeds_p-np.array([0.,size[1],0.]),seeds_p,seeds_p+np.array([0.,size[1],0.])))
|
||||||
seeds_p = np.vstack((seeds_p-np.array([0.,0.,size[2]]),seeds_p,seeds_p+np.array([0.,0.,size[2]])))
|
seeds_p = np.vstack((seeds_p-np.array([0.,0.,size[2]]),seeds_p,seeds_p+np.array([0.,0.,size[2]])))
|
||||||
else:
|
else:
|
||||||
weights_p = weights
|
weights_p = np.array(weights,float)
|
||||||
seeds_p = seeds
|
seeds_p = seeds
|
||||||
|
|
||||||
coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3)
|
coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3)
|
||||||
|
@ -421,29 +447,33 @@ class Grid:
|
||||||
|
|
||||||
if periodic: material_ %= len(weights)
|
if periodic: material_ %= len(weights)
|
||||||
|
|
||||||
return Grid(material = material_ if material is None else material[material_],
|
return Grid(material = material_ if material is None else np.array(material)[material_],
|
||||||
size = size,
|
size = size,
|
||||||
comments = util.execution_stamp('Grid','from_Laguerre_tessellation'),
|
comments = util.execution_stamp('Grid','from_Laguerre_tessellation'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_Voronoi_tessellation(cells,size,seeds,material=None,periodic=True):
|
def from_Voronoi_tessellation(cells: IntSequence,
|
||||||
|
size: FloatSequence,
|
||||||
|
seeds: np.ndarray,
|
||||||
|
material: IntSequence = None,
|
||||||
|
periodic: bool = True) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Create grid from Voronoi tessellation.
|
Create grid from Voronoi tessellation.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cells : int numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Number of cells in x,y,z direction.
|
Number of cells in x,y,z direction.
|
||||||
size : list or numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the grid in meter.
|
Physical size of the grid in meter.
|
||||||
seeds : numpy.ndarray of shape (:,3)
|
seeds : numpy.ndarray, shape (:,3)
|
||||||
Position of the seed points in meter. All points need to lay within the box.
|
Position of the seed points in meter. All points need to lay within the box.
|
||||||
material : numpy.ndarray of shape (seeds.shape[0]), optional
|
material : sequence of int, len (seeds.shape[0]), optional
|
||||||
Material ID of the seeds.
|
Material ID of the seeds.
|
||||||
Defaults to None, in which case materials are consecutively numbered.
|
Defaults to None, in which case materials are consecutively numbered.
|
||||||
periodic : Boolean, optional
|
periodic : bool, optional
|
||||||
Assume grid to be periodic. Defaults to True.
|
Assume grid to be periodic. Defaults to True.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -460,7 +490,7 @@ class Grid:
|
||||||
except TypeError:
|
except TypeError:
|
||||||
material_ = tree.query(coords, n_jobs = int(os.environ.get('OMP_NUM_THREADS',4)))[1] # scipy <1.6
|
material_ = tree.query(coords, n_jobs = int(os.environ.get('OMP_NUM_THREADS',4)))[1] # scipy <1.6
|
||||||
|
|
||||||
return Grid(material = (material_ if material is None else material[material_]).reshape(cells),
|
return Grid(material = (material_ if material is None else np.array(material)[material_]).reshape(cells),
|
||||||
size = size,
|
size = size,
|
||||||
comments = util.execution_stamp('Grid','from_Voronoi_tessellation'),
|
comments = util.execution_stamp('Grid','from_Voronoi_tessellation'),
|
||||||
)
|
)
|
||||||
|
@ -509,15 +539,20 @@ class Grid:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_minimal_surface(cells,size,surface,threshold=0.0,periods=1,materials=(0,1)):
|
def from_minimal_surface(cells: IntSequence,
|
||||||
|
size: FloatSequence,
|
||||||
|
surface: str,
|
||||||
|
threshold: float = 0.0,
|
||||||
|
periods: int = 1,
|
||||||
|
materials: IntSequence = (0,1)) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Create grid from definition of triply periodic minimal surface.
|
Create grid from definition of triply periodic minimal surface.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cells : int numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Number of cells in x,y,z direction.
|
Number of cells in x,y,z direction.
|
||||||
size : list or numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the grid in meter.
|
Physical size of the grid in meter.
|
||||||
surface : str
|
surface : str
|
||||||
Type of the minimal surface. See notes for details.
|
Type of the minimal surface. See notes for details.
|
||||||
|
@ -525,7 +560,7 @@ class Grid:
|
||||||
Threshold of the minimal surface. Defaults to 0.0.
|
Threshold of the minimal surface. Defaults to 0.0.
|
||||||
periods : integer, optional.
|
periods : integer, optional.
|
||||||
Number of periods per unit cell. Defaults to 1.
|
Number of periods per unit cell. Defaults to 1.
|
||||||
materials : (int, int), optional
|
materials : sequence of int, len (2)
|
||||||
Material IDs. Defaults to (0,1).
|
Material IDs. Defaults to (0,1).
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -566,22 +601,21 @@ class Grid:
|
||||||
|
|
||||||
>>> import numpy as np
|
>>> import numpy as np
|
||||||
>>> import damask
|
>>> import damask
|
||||||
>>> damask.Grid.from_minimal_surface(np.array([64]*3,int),np.ones(3),
|
>>> damask.Grid.from_minimal_surface([64]*3,np.ones(3)*1.e-4,'Gyroid')
|
||||||
... 'Gyroid')
|
cells : 64 x 64 x 64
|
||||||
cells a b c: 64 x 64 x 64
|
size : 0.0001 x 0.0001 x 0.0001 / m³
|
||||||
size x y z: 1.0 x 1.0 x 1.0
|
origin: 0.0 0.0 0.0 / m
|
||||||
origin x y z: 0.0 0.0 0.0
|
|
||||||
# materials: 2
|
# materials: 2
|
||||||
|
|
||||||
Minimal surface of 'Neovius' type. non-default material IDs.
|
Minimal surface of 'Neovius' type. non-default material IDs.
|
||||||
|
|
||||||
>>> import numpy as np
|
>>> import numpy as np
|
||||||
>>> import damask
|
>>> import damask
|
||||||
>>> damask.Grid.from_minimal_surface(np.array([80]*3,int),np.ones(3),
|
>>> damask.Grid.from_minimal_surface([80]*3,np.ones(3)*5.e-4,
|
||||||
... 'Neovius',materials=(1,5))
|
... 'Neovius',materials=(1,5))
|
||||||
cells a b c: 80 x 80 x 80
|
cells : 80 x 80 x 80
|
||||||
size x y z: 1.0 x 1.0 x 1.0
|
size : 0.0005 x 0.0005 x 0.0005 / m³
|
||||||
origin x y z: 0.0 0.0 0.0
|
origin: 0.0 0.0 0.0 / m
|
||||||
# materials: 2 (min: 1, max: 5)
|
# materials: 2 (min: 1, max: 5)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -595,7 +629,9 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def save(self,fname,compress=True):
|
def save(self,
|
||||||
|
fname: Union[str, Path],
|
||||||
|
compress: bool = True):
|
||||||
"""
|
"""
|
||||||
Save as VTK image data file.
|
Save as VTK image data file.
|
||||||
|
|
||||||
|
@ -611,10 +647,11 @@ class Grid:
|
||||||
v.add(self.material.flatten(order='F'),'material')
|
v.add(self.material.flatten(order='F'),'material')
|
||||||
v.add_comments(self.comments)
|
v.add_comments(self.comments)
|
||||||
|
|
||||||
v.save(fname if str(fname).endswith('.vti') else str(fname)+'.vti',parallel=False,compress=compress)
|
v.save(fname,parallel=False,compress=compress)
|
||||||
|
|
||||||
|
|
||||||
def save_ASCII(self,fname):
|
def save_ASCII(self,
|
||||||
|
fname: Union[str, TextIO]):
|
||||||
"""
|
"""
|
||||||
Save as geom file.
|
Save as geom file.
|
||||||
|
|
||||||
|
@ -644,26 +681,33 @@ class Grid:
|
||||||
header='\n'.join(header), fmt=format_string, comments='')
|
header='\n'.join(header), fmt=format_string, comments='')
|
||||||
|
|
||||||
|
|
||||||
def show(self):
|
def show(self) -> None:
|
||||||
"""Show on screen."""
|
"""Show on screen."""
|
||||||
VTK.from_rectilinear_grid(self.cells,self.size,self.origin).show()
|
VTK.from_image_data(self.cells,self.size,self.origin).show()
|
||||||
|
|
||||||
|
|
||||||
def add_primitive(self,dimension,center,exponent,
|
def add_primitive(self,
|
||||||
fill=None,R=Rotation(),inverse=False,periodic=True):
|
dimension: Union[FloatSequence, IntSequence],
|
||||||
|
center: Union[FloatSequence, IntSequence],
|
||||||
|
exponent: Union[FloatSequence, float],
|
||||||
|
fill: int = None,
|
||||||
|
R: Rotation = Rotation(),
|
||||||
|
inverse: bool = False,
|
||||||
|
periodic: bool = True) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Insert a primitive geometric object at a given position.
|
Insert a primitive geometric object at a given position.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
dimension : int or float numpy.ndarray of shape (3)
|
dimension : sequence of int or float, len (3)
|
||||||
Dimension (diameter/side length) of the primitive. If given as
|
Dimension (diameter/side length) of the primitive.
|
||||||
integers, cell centers are addressed.
|
If given as integers, cell centers are addressed.
|
||||||
If given as floats, coordinates are addressed.
|
If given as floats, physical coordinates are addressed.
|
||||||
center : int or float numpy.ndarray of shape (3)
|
center : sequence of int or float, len (3)
|
||||||
Center of the primitive. If given as integers, cell centers are addressed.
|
Center of the primitive.
|
||||||
If given as floats, coordinates in space are addressed.
|
If given as integers, cell centers are addressed.
|
||||||
exponent : numpy.ndarray of shape (3) or float
|
If given as floats, physical coordinates are addressed.
|
||||||
|
exponent : float or sequence of float, len (3)
|
||||||
Exponents for the three axes.
|
Exponents for the three axes.
|
||||||
0 gives octahedron (ǀxǀ^(2^0) + ǀyǀ^(2^0) + ǀzǀ^(2^0) < 1)
|
0 gives octahedron (ǀxǀ^(2^0) + ǀyǀ^(2^0) + ǀzǀ^(2^0) < 1)
|
||||||
1 gives sphere (ǀxǀ^(2^1) + ǀyǀ^(2^1) + ǀzǀ^(2^1) < 1)
|
1 gives sphere (ǀxǀ^(2^1) + ǀyǀ^(2^1) + ǀzǀ^(2^1) < 1)
|
||||||
|
@ -671,10 +715,10 @@ class Grid:
|
||||||
Fill value for primitive. Defaults to material.max()+1.
|
Fill value for primitive. Defaults to material.max()+1.
|
||||||
R : damask.Rotation, optional
|
R : damask.Rotation, optional
|
||||||
Rotation of primitive. Defaults to no rotation.
|
Rotation of primitive. Defaults to no rotation.
|
||||||
inverse : Boolean, optional
|
inverse : bool, optional
|
||||||
Retain original materials within primitive and fill outside.
|
Retain original materials within primitive and fill outside.
|
||||||
Defaults to False.
|
Defaults to False.
|
||||||
periodic : Boolean, optional
|
periodic : bool, optional
|
||||||
Assume grid to be periodic. Defaults to True.
|
Assume grid to be periodic. Defaults to True.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -690,9 +734,9 @@ class Grid:
|
||||||
>>> import damask
|
>>> import damask
|
||||||
>>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4)
|
>>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4)
|
||||||
>>> g.add_primitive(np.ones(3)*5e-5,np.ones(3)*5e-5,1)
|
>>> g.add_primitive(np.ones(3)*5e-5,np.ones(3)*5e-5,1)
|
||||||
cells a b c: 64 x 64 x 64
|
cells : 64 x 64 x 64
|
||||||
size x y z: 0.0001 x 0.0001 x 0.0001
|
size : 0.0001 x 0.0001 x 0.0001 / m³
|
||||||
origin x y z: 0.0 0.0 0.0
|
origin: 0.0 0.0 0.0 / m
|
||||||
# materials: 2
|
# materials: 2
|
||||||
|
|
||||||
Add a cube at the origin.
|
Add a cube at the origin.
|
||||||
|
@ -701,9 +745,9 @@ class Grid:
|
||||||
>>> import damask
|
>>> import damask
|
||||||
>>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4)
|
>>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4)
|
||||||
>>> g.add_primitive(np.ones(3,int)*32,np.zeros(3),np.inf)
|
>>> g.add_primitive(np.ones(3,int)*32,np.zeros(3),np.inf)
|
||||||
cells a b c: 64 x 64 x 64
|
cells : 64 x 64 x 64
|
||||||
size x y z: 0.0001 x 0.0001 x 0.0001
|
size : 0.0001 x 0.0001 x 0.0001 / m³
|
||||||
origin x y z: 0.0 0.0 0.0
|
origin: 0.0 0.0 0.0 / m
|
||||||
# materials: 2
|
# materials: 2
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -734,15 +778,16 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def mirror(self,directions,reflect=False):
|
def mirror(self,
|
||||||
|
directions: Sequence[str],
|
||||||
|
reflect: bool = False) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Mirror grid along given directions.
|
Mirror grid along given directions.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
directions : iterable containing str
|
directions : (sequence of) {'x', 'y', 'z'}
|
||||||
Direction(s) along which the grid is mirrored.
|
Direction(s) along which the grid is mirrored.
|
||||||
Valid entries are 'x', 'y', 'z'.
|
|
||||||
reflect : bool, optional
|
reflect : bool, optional
|
||||||
Reflect (include) outermost layers. Defaults to False.
|
Reflect (include) outermost layers. Defaults to False.
|
||||||
|
|
||||||
|
@ -759,17 +804,16 @@ class Grid:
|
||||||
>>> import damask
|
>>> import damask
|
||||||
>>> g = damask.Grid(np.zeros([32]*3,int), np.ones(3)*1e-4)
|
>>> g = damask.Grid(np.zeros([32]*3,int), np.ones(3)*1e-4)
|
||||||
>>> g.mirror('xy',True)
|
>>> g.mirror('xy',True)
|
||||||
cells a b c: 64 x 64 x 32
|
cells : 64 x 64 x 32
|
||||||
size x y z: 0.0002 x 0.0002 x 0.0001
|
size : 0.0002 x 0.0002 x 0.0001 / m³
|
||||||
origin x y z: 0.0 0.0 0.0
|
origin: 0.0 0.0 0.0 / m
|
||||||
# materials: 1
|
# materials: 1
|
||||||
|
|
||||||
"""
|
"""
|
||||||
valid = ['x','y','z']
|
if not set(directions).issubset(valid := ['x', 'y', 'z']):
|
||||||
if not set(directions).issubset(valid):
|
|
||||||
raise ValueError(f'invalid direction {set(directions).difference(valid)} specified')
|
raise ValueError(f'invalid direction {set(directions).difference(valid)} specified')
|
||||||
|
|
||||||
limits = [None,None] if reflect else [-2,0]
|
limits: Sequence[Optional[int]] = [None,None] if reflect else [-2,0]
|
||||||
mat = self.material.copy()
|
mat = self.material.copy()
|
||||||
|
|
||||||
if 'x' in directions:
|
if 'x' in directions:
|
||||||
|
@ -786,15 +830,15 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def flip(self,directions):
|
def flip(self,
|
||||||
|
directions: Sequence[str]) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Flip grid along given directions.
|
Flip grid along given directions.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
directions : iterable containing str
|
directions : (sequence of) {'x', 'y', 'z'}
|
||||||
Direction(s) along which the grid is flipped.
|
Direction(s) along which the grid is flipped.
|
||||||
Valid entries are 'x', 'y', 'z'.
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
@ -802,11 +846,11 @@ class Grid:
|
||||||
Updated grid-based geometry.
|
Updated grid-based geometry.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
valid = ['x','y','z']
|
if not set(directions).issubset(valid := ['x', 'y', 'z']):
|
||||||
if not set(directions).issubset(valid):
|
|
||||||
raise ValueError(f'invalid direction {set(directions).difference(valid)} specified')
|
raise ValueError(f'invalid direction {set(directions).difference(valid)} specified')
|
||||||
|
|
||||||
mat = np.flip(self.material, (valid.index(d) for d in directions if d in valid))
|
|
||||||
|
mat = np.flip(self.material, [valid.index(d) for d in directions if d in valid])
|
||||||
|
|
||||||
return Grid(material = mat,
|
return Grid(material = mat,
|
||||||
size = self.size,
|
size = self.size,
|
||||||
|
@ -815,15 +859,17 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def scale(self,cells,periodic=True):
|
def scale(self,
|
||||||
|
cells: IntSequence,
|
||||||
|
periodic: bool = True) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Scale grid to new cells.
|
Scale grid to new cells.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cells : numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Number of cells in x,y,z direction.
|
Number of cells in x,y,z direction.
|
||||||
periodic : Boolean, optional
|
periodic : bool, optional
|
||||||
Assume grid to be periodic. Defaults to True.
|
Assume grid to be periodic. Defaults to True.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -839,9 +885,9 @@ class Grid:
|
||||||
>>> import damask
|
>>> import damask
|
||||||
>>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4)
|
>>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4)
|
||||||
>>> g.scale(g.cells*2)
|
>>> g.scale(g.cells*2)
|
||||||
cells a b c: 64 x 64 x 64
|
cells : 64 x 64 x 64
|
||||||
size x y z: 0.0001 x 0.0001 x 0.0001
|
size : 0.0001 x 0.0001 x 0.0001 / m³
|
||||||
origin x y z: 0.0 0.0 0.0
|
origin: 0.0 0.0 0.0 / m
|
||||||
# materials: 1
|
# materials: 1
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -859,7 +905,10 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def clean(self,stencil=3,selection=None,periodic=True):
|
def clean(self,
|
||||||
|
stencil: int = 3,
|
||||||
|
selection: IntSequence = None,
|
||||||
|
periodic: bool = True) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Smooth grid by selecting most frequent material index within given stencil at each location.
|
Smooth grid by selecting most frequent material index within given stencil at each location.
|
||||||
|
|
||||||
|
@ -867,9 +916,9 @@ class Grid:
|
||||||
----------
|
----------
|
||||||
stencil : int, optional
|
stencil : int, optional
|
||||||
Size of smoothing stencil.
|
Size of smoothing stencil.
|
||||||
selection : list, optional
|
selection : sequence of int, optional
|
||||||
Field values that can be altered. Defaults to all.
|
Field values that can be altered. Defaults to all.
|
||||||
periodic : Boolean, optional
|
periodic : bool, optional
|
||||||
Assume grid to be periodic. Defaults to True.
|
Assume grid to be periodic. Defaults to True.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -878,7 +927,7 @@ class Grid:
|
||||||
Updated grid-based geometry.
|
Updated grid-based geometry.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def mostFrequent(arr,selection=None):
|
def mostFrequent(arr: np.ndarray, selection = None):
|
||||||
me = arr[arr.size//2]
|
me = arr[arr.size//2]
|
||||||
if selection is None or me in selection:
|
if selection is None or me in selection:
|
||||||
unique, inverse = np.unique(arr, return_inverse=True)
|
unique, inverse = np.unique(arr, return_inverse=True)
|
||||||
|
@ -899,7 +948,7 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def renumber(self):
|
def renumber(self) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Renumber sorted material indices as 0,...,N-1.
|
Renumber sorted material indices as 0,...,N-1.
|
||||||
|
|
||||||
|
@ -918,7 +967,9 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def rotate(self,R,fill=None):
|
def rotate(self,
|
||||||
|
R: Rotation,
|
||||||
|
fill: int = None) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Rotate grid (pad if required).
|
Rotate grid (pad if required).
|
||||||
|
|
||||||
|
@ -926,7 +977,7 @@ class Grid:
|
||||||
----------
|
----------
|
||||||
R : damask.Rotation
|
R : damask.Rotation
|
||||||
Rotation to apply to the grid.
|
Rotation to apply to the grid.
|
||||||
fill : int or float, optional
|
fill : int, optional
|
||||||
Material index to fill the corners. Defaults to material.max() + 1.
|
Material index to fill the corners. Defaults to material.max() + 1.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -935,14 +986,13 @@ class Grid:
|
||||||
Updated grid-based geometry.
|
Updated grid-based geometry.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if fill is None: fill = np.nanmax(self.material) + 1
|
|
||||||
dtype = float if isinstance(fill,float) or self.material.dtype in np.sctypes['float'] else int
|
|
||||||
|
|
||||||
material = self.material
|
material = self.material
|
||||||
# These rotations are always applied in the reference coordinate system, i.e. (z,x,z) not (z,x',z'')
|
# These rotations are always applied in the reference coordinate system, i.e. (z,x,z) not (z,x',z'')
|
||||||
# see https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf
|
# see https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf
|
||||||
for angle,axes in zip(R.as_Euler_angles(degrees=True)[::-1], [(0,1),(1,2),(0,1)]):
|
for angle,axes in zip(R.as_Euler_angles(degrees=True)[::-1], [(0,1),(1,2),(0,1)]):
|
||||||
material_temp = ndimage.rotate(material,angle,axes,order=0,prefilter=False,output=dtype,cval=fill)
|
material_temp = ndimage.rotate(material,angle,axes,order=0,prefilter=False,
|
||||||
|
output=self.material.dtype,
|
||||||
|
cval=np.nanmax(self.material) + 1 if fill is None else fill)
|
||||||
# avoid scipy interpolation errors for rotations close to multiples of 90°
|
# avoid scipy interpolation errors for rotations close to multiples of 90°
|
||||||
material = material_temp if np.prod(material_temp.shape) != np.prod(material.shape) else \
|
material = material_temp if np.prod(material_temp.shape) != np.prod(material.shape) else \
|
||||||
np.rot90(material,k=np.rint(angle/90.).astype(int),axes=axes)
|
np.rot90(material,k=np.rint(angle/90.).astype(int),axes=axes)
|
||||||
|
@ -956,17 +1006,20 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def canvas(self,cells=None,offset=None,fill=None):
|
def canvas(self,
|
||||||
|
cells: IntSequence = None,
|
||||||
|
offset: IntSequence = None,
|
||||||
|
fill: int = None) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Crop or enlarge/pad grid.
|
Crop or enlarge/pad grid.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cells : numpy.ndarray of shape (3)
|
cells : sequence of int, len (3), optional
|
||||||
Number of cells x,y,z direction.
|
Number of cells x,y,z direction.
|
||||||
offset : numpy.ndarray of shape (3)
|
offset : sequence of int, len (3), optional
|
||||||
Offset (measured in cells) from old to new grid [0,0,0].
|
Offset (measured in cells) from old to new grid [0,0,0].
|
||||||
fill : int or float, optional
|
fill : int, optional
|
||||||
Material index to fill the background. Defaults to material.max() + 1.
|
Material index to fill the background. Defaults to material.max() + 1.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -981,42 +1034,43 @@ class Grid:
|
||||||
>>> import numpy as np
|
>>> import numpy as np
|
||||||
>>> import damask
|
>>> import damask
|
||||||
>>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4)
|
>>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4)
|
||||||
>>> g.canvas(np.array([32,32,16],int))
|
>>> g.canvas([32,32,16])
|
||||||
cells a b c: 33 x 32 x 16
|
cells : 33 x 32 x 16
|
||||||
size x y z: 0.0001 x 0.0001 x 5e-05
|
size : 0.0001 x 0.0001 x 5e-05 / m³
|
||||||
origin x y z: 0.0 0.0 0.0
|
origin: 0.0 0.0 0.0 / m
|
||||||
# materials: 1
|
# materials: 1
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if offset is None: offset = 0
|
offset_ = np.array(offset,int) if offset is not None else np.zeros(3,int)
|
||||||
if fill is None: fill = np.nanmax(self.material) + 1
|
cells_ = np.array(cells,int) if cells is not None else self.cells
|
||||||
dtype = float if int(fill) != fill or self.material.dtype in np.sctypes['float'] else int
|
|
||||||
|
|
||||||
canvas = np.full(self.cells if cells is None else cells,fill,dtype)
|
canvas = np.full(cells_,np.nanmax(self.material) + 1 if fill is None else fill,self.material.dtype)
|
||||||
|
|
||||||
LL = np.clip( offset, 0,np.minimum(self.cells, cells+offset))
|
LL = np.clip( offset_, 0,np.minimum(self.cells, cells_+offset_))
|
||||||
UR = np.clip( offset+cells, 0,np.minimum(self.cells, cells+offset))
|
UR = np.clip( offset_+cells_, 0,np.minimum(self.cells, cells_+offset_))
|
||||||
ll = np.clip(-offset, 0,np.minimum( cells,self.cells-offset))
|
ll = np.clip(-offset_, 0,np.minimum( cells_,self.cells-offset_))
|
||||||
ur = np.clip(-offset+self.cells,0,np.minimum( cells,self.cells-offset))
|
ur = np.clip(-offset_+self.cells,0,np.minimum( cells_,self.cells-offset_))
|
||||||
|
|
||||||
canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.material[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]]
|
canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.material[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]]
|
||||||
|
|
||||||
return Grid(material = canvas,
|
return Grid(material = canvas,
|
||||||
size = self.size/self.cells*np.asarray(canvas.shape),
|
size = self.size/self.cells*np.asarray(canvas.shape),
|
||||||
origin = self.origin+offset*self.size/self.cells,
|
origin = self.origin+offset_*self.size/self.cells,
|
||||||
comments = self.comments+[util.execution_stamp('Grid','canvas')],
|
comments = self.comments+[util.execution_stamp('Grid','canvas')],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def substitute(self,from_material,to_material):
|
def substitute(self,
|
||||||
|
from_material: IntSequence,
|
||||||
|
to_material: IntSequence) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Substitute material indices.
|
Substitute material indices.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
from_material : iterable of ints
|
from_material : sequence of int
|
||||||
Material indices to be substituted.
|
Material indices to be substituted.
|
||||||
to_material : iterable of ints
|
to_material : sequence of int
|
||||||
New material indices.
|
New material indices.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -1025,20 +1079,18 @@ class Grid:
|
||||||
Updated grid-based geometry.
|
Updated grid-based geometry.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def mp(entry,mapper):
|
material = self.material.copy()
|
||||||
return mapper[entry] if entry in mapper else entry
|
for f,t in zip(from_material,to_material): # ToDo Python 3.10 has strict mode for zip
|
||||||
|
material[self.material==f] = t
|
||||||
|
|
||||||
mp = np.vectorize(mp)
|
return Grid(material = material,
|
||||||
mapper = dict(zip(from_material,to_material))
|
|
||||||
|
|
||||||
return Grid(material = mp(self.material,mapper).reshape(self.cells),
|
|
||||||
size = self.size,
|
size = self.size,
|
||||||
origin = self.origin,
|
origin = self.origin,
|
||||||
comments = self.comments+[util.execution_stamp('Grid','substitute')],
|
comments = self.comments+[util.execution_stamp('Grid','substitute')],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def sort(self):
|
def sort(self) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Sort material indices such that min(material) is located at (0,0,0).
|
Sort material indices such that min(material) is located at (0,0,0).
|
||||||
|
|
||||||
|
@ -1060,7 +1112,11 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def vicinity_offset(self,vicinity=1,offset=None,trigger=[],periodic=True):
|
def vicinity_offset(self,
|
||||||
|
vicinity: int = 1,
|
||||||
|
offset: int = None,
|
||||||
|
trigger: IntSequence = [],
|
||||||
|
periodic: bool = True) -> 'Grid':
|
||||||
"""
|
"""
|
||||||
Offset material index of points in the vicinity of xxx.
|
Offset material index of points in the vicinity of xxx.
|
||||||
|
|
||||||
|
@ -1076,10 +1132,10 @@ class Grid:
|
||||||
offset : int, optional
|
offset : int, optional
|
||||||
Offset (positive or negative) to tag material indices,
|
Offset (positive or negative) to tag material indices,
|
||||||
defaults to material.max()+1.
|
defaults to material.max()+1.
|
||||||
trigger : list of ints, optional
|
trigger : sequence of int, optional
|
||||||
List of material indices that trigger a change.
|
List of material indices that trigger a change.
|
||||||
Defaults to [], meaning that any different neighbor triggers a change.
|
Defaults to [], meaning that any different neighbor triggers a change.
|
||||||
periodic : Boolean, optional
|
periodic : bool, optional
|
||||||
Assume grid to be periodic. Defaults to True.
|
Assume grid to be periodic. Defaults to True.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -1088,8 +1144,7 @@ class Grid:
|
||||||
Updated grid-based geometry.
|
Updated grid-based geometry.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def tainted_neighborhood(stencil,trigger):
|
def tainted_neighborhood(stencil: np.ndarray, trigger):
|
||||||
|
|
||||||
me = stencil[stencil.shape[0]//2]
|
me = stencil[stencil.shape[0]//2]
|
||||||
return np.any(stencil != me if len(trigger) == 0 else
|
return np.any(stencil != me if len(trigger) == 0 else
|
||||||
np.in1d(stencil,np.array(list(set(trigger) - {me}))))
|
np.in1d(stencil,np.array(list(set(trigger) - {me}))))
|
||||||
|
@ -1108,17 +1163,19 @@ class Grid:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_grain_boundaries(self,periodic=True,directions='xyz'):
|
def get_grain_boundaries(self,
|
||||||
|
periodic: bool = True,
|
||||||
|
directions: Sequence[str] = 'xyz') -> VTK:
|
||||||
"""
|
"""
|
||||||
Create VTK unstructured grid containing grain boundaries.
|
Create VTK unstructured grid containing grain boundaries.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
periodic : Boolean, optional
|
periodic : bool, optional
|
||||||
Assume grid to be periodic. Defaults to True.
|
Assume grid to be periodic. Defaults to True.
|
||||||
directions : iterable containing str, optional
|
directions : (sequence of) {'x', 'y', 'z'}, optional
|
||||||
Direction(s) along which the boundaries are determined.
|
Direction(s) along which the boundaries are determined.
|
||||||
Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'.
|
Defaults to 'xyz'.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
@ -1126,8 +1183,7 @@ class Grid:
|
||||||
VTK-based geometry of grain boundary network.
|
VTK-based geometry of grain boundary network.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
valid = ['x','y','z']
|
if not set(directions).issubset(valid := ['x', 'y', 'z']):
|
||||||
if not set(directions).issubset(valid):
|
|
||||||
raise ValueError(f'invalid direction {set(directions).difference(valid)} specified')
|
raise ValueError(f'invalid direction {set(directions).difference(valid)} specified')
|
||||||
|
|
||||||
o = [[0, self.cells[0]+1, np.prod(self.cells[:2]+1)+self.cells[0]+1, np.prod(self.cells[:2]+1)],
|
o = [[0, self.cells[0]+1, np.prod(self.cells[:2]+1)+self.cells[0]+1, np.prod(self.cells[:2]+1)],
|
||||||
|
|
|
@ -393,8 +393,8 @@ class Orientation(Rotation,Crystal):
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
in : numpy.ndarray of quaternion.shape
|
in : numpy.ndarray of bool, quaternion.shape
|
||||||
Boolean array indicating whether Rodrigues-Frank vector falls into fundamental zone.
|
Whether Rodrigues-Frank vector falls into fundamental zone.
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
|
@ -437,8 +437,8 @@ class Orientation(Rotation,Crystal):
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
in : numpy.ndarray of quaternion.shape
|
in : numpy.ndarray of bool, quaternion.shape
|
||||||
Boolean array indicating whether Rodrigues-Frank vector falls into disorientation FZ.
|
Whether Rodrigues-Frank vector falls into disorientation FZ.
|
||||||
|
|
||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
|
@ -651,8 +651,8 @@ class Orientation(Rotation,Crystal):
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
in : numpy.ndarray of shape (...)
|
in : numpy.ndarray, shape (...)
|
||||||
Boolean array indicating whether vector falls into SST.
|
Whether vector falls into SST.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not isinstance(vector,np.ndarray) or vector.shape[-1] != 3:
|
if not isinstance(vector,np.ndarray) or vector.shape[-1] != 3:
|
||||||
|
|
|
@ -981,7 +981,7 @@ class Result:
|
||||||
t = 'tensor'
|
t = 'tensor'
|
||||||
if o is None: o = 'fro'
|
if o is None: o = 'fro'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'invalid norm order {ord}')
|
raise ValueError(f'invalid shape of {x["label"]}')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'data': np.linalg.norm(x['data'],ord=o,axis=axis,keepdims=True),
|
'data': np.linalg.norm(x['data'],ord=o,axis=axis,keepdims=True),
|
||||||
|
@ -1817,7 +1817,7 @@ class Result:
|
||||||
output : (list of) str, optional
|
output : (list of) str, optional
|
||||||
Names of the datasets to export to the file.
|
Names of the datasets to export to the file.
|
||||||
Defaults to '*', in which case all datasets are exported.
|
Defaults to '*', in which case all datasets are exported.
|
||||||
overwrite : boolean, optional
|
overwrite : bool, optional
|
||||||
Overwrite existing configuration files.
|
Overwrite existing configuration files.
|
||||||
Defaults to False.
|
Defaults to False.
|
||||||
|
|
||||||
|
|
|
@ -671,7 +671,7 @@ class Rotation:
|
||||||
----------
|
----------
|
||||||
q : numpy.ndarray of shape (...,4)
|
q : numpy.ndarray of shape (...,4)
|
||||||
Unit quaternion (q_0, q_1, q_2, q_3) in positive real hemisphere, i.e. ǀqǀ = 1, q_0 ≥ 0.
|
Unit quaternion (q_0, q_1, q_2, q_3) in positive real hemisphere, i.e. ǀqǀ = 1, q_0 ≥ 0.
|
||||||
accept_homomorph : boolean, optional
|
accept_homomorph : bool, optional
|
||||||
Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere).
|
Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere).
|
||||||
Defaults to False.
|
Defaults to False.
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
|
@ -706,7 +706,7 @@ class Rotation:
|
||||||
phi : numpy.ndarray of shape (...,3)
|
phi : numpy.ndarray of shape (...,3)
|
||||||
Euler angles (φ_1 ∈ [0,2π], ϕ ∈ [0,π], φ_2 ∈ [0,2π])
|
Euler angles (φ_1 ∈ [0,2π], ϕ ∈ [0,π], φ_2 ∈ [0,2π])
|
||||||
or (φ_1 ∈ [0,360], ϕ ∈ [0,180], φ_2 ∈ [0,360]) if degrees == True.
|
or (φ_1 ∈ [0,360], ϕ ∈ [0,180], φ_2 ∈ [0,360]) if degrees == True.
|
||||||
degrees : boolean, optional
|
degrees : bool, optional
|
||||||
Euler angles are given in degrees. Defaults to False.
|
Euler angles are given in degrees. Defaults to False.
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
|
@ -737,9 +737,9 @@ class Rotation:
|
||||||
axis_angle : numpy.ndarray of shape (...,4)
|
axis_angle : numpy.ndarray of shape (...,4)
|
||||||
Axis and angle (n_1, n_2, n_3, ω) with ǀnǀ = 1 and ω ∈ [0,π]
|
Axis and angle (n_1, n_2, n_3, ω) with ǀnǀ = 1 and ω ∈ [0,π]
|
||||||
or ω ∈ [0,180] if degrees == True.
|
or ω ∈ [0,180] if degrees == True.
|
||||||
degrees : boolean, optional
|
degrees : bool, optional
|
||||||
Angle ω is given in degrees. Defaults to False.
|
Angle ω is given in degrees. Defaults to False.
|
||||||
normalize: boolean, optional
|
normalize: bool, optional
|
||||||
Allow ǀnǀ ≠ 1. Defaults to False.
|
Allow ǀnǀ ≠ 1. Defaults to False.
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Sign convention. Defaults to -1.
|
Sign convention. Defaults to -1.
|
||||||
|
@ -773,9 +773,9 @@ class Rotation:
|
||||||
----------
|
----------
|
||||||
basis : numpy.ndarray of shape (...,3,3)
|
basis : numpy.ndarray of shape (...,3,3)
|
||||||
Three three-dimensional lattice basis vectors.
|
Three three-dimensional lattice basis vectors.
|
||||||
orthonormal : boolean, optional
|
orthonormal : bool, optional
|
||||||
Basis is strictly orthonormal, i.e. is free of stretch components. Defaults to True.
|
Basis is strictly orthonormal, i.e. is free of stretch components. Defaults to True.
|
||||||
reciprocal : boolean, optional
|
reciprocal : bool, optional
|
||||||
Basis vectors are given in reciprocal (instead of real) space. Defaults to False.
|
Basis vectors are given in reciprocal (instead of real) space. Defaults to False.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -812,8 +812,7 @@ class Rotation:
|
||||||
return Rotation.from_basis(R)
|
return Rotation.from_basis(R)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_parallel(a,b,
|
def from_parallel(a,b):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from pairs of two orthogonal lattice basis vectors.
|
Initialize from pairs of two orthogonal lattice basis vectors.
|
||||||
|
|
||||||
|
@ -851,7 +850,7 @@ class Rotation:
|
||||||
----------
|
----------
|
||||||
rho : numpy.ndarray of shape (...,4)
|
rho : numpy.ndarray of shape (...,4)
|
||||||
Rodrigues–Frank vector (n_1, n_2, n_3, tan(ω/2)) with ǀnǀ = 1 and ω ∈ [0,π].
|
Rodrigues–Frank vector (n_1, n_2, n_3, tan(ω/2)) with ǀnǀ = 1 and ω ∈ [0,π].
|
||||||
normalize : boolean, optional
|
normalize : bool, optional
|
||||||
Allow ǀnǀ ≠ 1. Defaults to False.
|
Allow ǀnǀ ≠ 1. Defaults to False.
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Sign convention. Defaults to -1.
|
Sign convention. Defaults to -1.
|
||||||
|
@ -963,8 +962,7 @@ class Rotation:
|
||||||
N = 500,
|
N = 500,
|
||||||
degrees = True,
|
degrees = True,
|
||||||
fractions = True,
|
fractions = True,
|
||||||
rng_seed = None,
|
rng_seed = None):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Sample discrete values from a binned orientation distribution function (ODF).
|
Sample discrete values from a binned orientation distribution function (ODF).
|
||||||
|
|
||||||
|
@ -977,9 +975,9 @@ class Rotation:
|
||||||
N : integer, optional
|
N : integer, optional
|
||||||
Number of discrete orientations to be sampled from the given ODF.
|
Number of discrete orientations to be sampled from the given ODF.
|
||||||
Defaults to 500.
|
Defaults to 500.
|
||||||
degrees : boolean, optional
|
degrees : bool, optional
|
||||||
Euler space grid coordinates are in degrees. Defaults to True.
|
Euler space grid coordinates are in degrees. Defaults to True.
|
||||||
fractions : boolean, optional
|
fractions : bool, optional
|
||||||
ODF values correspond to volume fractions, not probability densities.
|
ODF values correspond to volume fractions, not probability densities.
|
||||||
Defaults to True.
|
Defaults to True.
|
||||||
rng_seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
rng_seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
||||||
|
@ -1033,7 +1031,7 @@ class Rotation:
|
||||||
Standard deviation of (Gaussian) misorientation distribution.
|
Standard deviation of (Gaussian) misorientation distribution.
|
||||||
N : int, optional
|
N : int, optional
|
||||||
Number of samples. Defaults to 500.
|
Number of samples. Defaults to 500.
|
||||||
degrees : boolean, optional
|
degrees : bool, optional
|
||||||
sigma is given in degrees. Defaults to True.
|
sigma is given in degrees. Defaults to True.
|
||||||
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
||||||
A seed to initialize the BitGenerator.
|
A seed to initialize the BitGenerator.
|
||||||
|
@ -1072,7 +1070,7 @@ class Rotation:
|
||||||
Defaults to 0.
|
Defaults to 0.
|
||||||
N : int, optional
|
N : int, optional
|
||||||
Number of samples. Defaults to 500.
|
Number of samples. Defaults to 500.
|
||||||
degrees : boolean, optional
|
degrees : bool, optional
|
||||||
sigma, alpha, and beta are given in degrees.
|
sigma, alpha, and beta are given in degrees.
|
||||||
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
||||||
A seed to initialize the BitGenerator.
|
A seed to initialize the BitGenerator.
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
import re
|
import re
|
||||||
import copy
|
import copy
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Union, Tuple, List
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
from ._typehints import FileHandle
|
||||||
from . import util
|
from . import util
|
||||||
|
|
||||||
class Table:
|
class Table:
|
||||||
"""Manipulate multi-dimensional spreadsheet-like data."""
|
"""Manipulate multi-dimensional spreadsheet-like data."""
|
||||||
|
|
||||||
def __init__(self,data,shapes,comments=None):
|
def __init__(self,
|
||||||
|
data: np.ndarray,
|
||||||
|
shapes: dict,
|
||||||
|
comments: Union[str, list] = None):
|
||||||
"""
|
"""
|
||||||
New spreadsheet.
|
New spreadsheet.
|
||||||
|
|
||||||
|
@ -30,7 +36,7 @@ class Table:
|
||||||
self._relabel('uniform')
|
self._relabel('uniform')
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
"""Brief overview."""
|
"""Brief overview."""
|
||||||
self._relabel('shapes')
|
self._relabel('shapes')
|
||||||
data_repr = self.data.__repr__()
|
data_repr = self.data.__repr__()
|
||||||
|
@ -38,7 +44,8 @@ class Table:
|
||||||
return '\n'.join(['# '+c for c in self.comments])+'\n'+data_repr
|
return '\n'.join(['# '+c for c in self.comments])+'\n'+data_repr
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self,item):
|
def __getitem__(self,
|
||||||
|
item: Union[slice, Tuple[slice, ...]]) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Slice the Table according to item.
|
Slice the Table according to item.
|
||||||
|
|
||||||
|
@ -85,19 +92,21 @@ class Table:
|
||||||
comments=self.comments)
|
comments=self.comments)
|
||||||
|
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self) -> int:
|
||||||
"""Number of rows."""
|
"""Number of rows."""
|
||||||
return len(self.data)
|
return len(self.data)
|
||||||
|
|
||||||
|
|
||||||
def __copy__(self):
|
def __copy__(self) -> 'Table':
|
||||||
"""Create deep copy."""
|
"""Create deep copy."""
|
||||||
return copy.deepcopy(self)
|
return copy.deepcopy(self)
|
||||||
|
|
||||||
copy = __copy__
|
copy = __copy__
|
||||||
|
|
||||||
|
|
||||||
def _label(self,what,how):
|
def _label(self,
|
||||||
|
what: Union[str, List[str]],
|
||||||
|
how: str) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Expand labels according to data shape.
|
Expand labels according to data shape.
|
||||||
|
|
||||||
|
@ -105,7 +114,7 @@ class Table:
|
||||||
----------
|
----------
|
||||||
what : str or list
|
what : str or list
|
||||||
Labels to expand.
|
Labels to expand.
|
||||||
how : str
|
how : {'uniform, 'shapes', 'linear'}
|
||||||
Mode of labeling.
|
Mode of labeling.
|
||||||
'uniform' ==> v v v
|
'uniform' ==> v v v
|
||||||
'shapes' ==> 3:v v v
|
'shapes' ==> 3:v v v
|
||||||
|
@ -128,30 +137,38 @@ class Table:
|
||||||
return labels
|
return labels
|
||||||
|
|
||||||
|
|
||||||
def _relabel(self,how):
|
def _relabel(self,
|
||||||
|
how: str):
|
||||||
"""
|
"""
|
||||||
Modify labeling of data in-place.
|
Modify labeling of data in-place.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
how : str
|
how : {'uniform, 'shapes', 'linear'}
|
||||||
Mode of labeling.
|
Mode of labeling.
|
||||||
'uniform' ==> v v v
|
'uniform' ==> v v v
|
||||||
'shapes' ==> 3:v v v
|
'shapes' ==> 3:v v v
|
||||||
'linear' ==> 1_v 2_v 3_v
|
'linear' ==> 1_v 2_v 3_v
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.data.columns = self._label(self.shapes,how)
|
self.data.columns = self._label(self.shapes,how) #type: ignore
|
||||||
|
|
||||||
|
|
||||||
def _add_comment(self,label,shape,info):
|
def _add_comment(self,
|
||||||
|
label: str,
|
||||||
|
shape: Tuple[int, ...],
|
||||||
|
info: str = None):
|
||||||
if info is not None:
|
if info is not None:
|
||||||
specific = f'{label}{" "+str(shape) if np.prod(shape,dtype=int) > 1 else ""}: {info}'
|
specific = f'{label}{" "+str(shape) if np.prod(shape,dtype=int) > 1 else ""}: {info}'
|
||||||
general = util.execution_stamp('Table')
|
general = util.execution_stamp('Table')
|
||||||
self.comments.append(f'{specific} / {general}')
|
self.comments.append(f'{specific} / {general}')
|
||||||
|
|
||||||
|
|
||||||
def isclose(self,other,rtol=1e-5,atol=1e-8,equal_nan=True):
|
def isclose(self,
|
||||||
|
other: 'Table',
|
||||||
|
rtol: float = 1e-5,
|
||||||
|
atol: float = 1e-8,
|
||||||
|
equal_nan: bool = True) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Report where values are approximately equal to corresponding ones of other Table.
|
Report where values are approximately equal to corresponding ones of other Table.
|
||||||
|
|
||||||
|
@ -179,7 +196,11 @@ class Table:
|
||||||
equal_nan=equal_nan)
|
equal_nan=equal_nan)
|
||||||
|
|
||||||
|
|
||||||
def allclose(self,other,rtol=1e-5,atol=1e-8,equal_nan=True):
|
def allclose(self,
|
||||||
|
other: 'Table',
|
||||||
|
rtol: float = 1e-5,
|
||||||
|
atol: float = 1e-8,
|
||||||
|
equal_nan: bool = True) -> bool:
|
||||||
"""
|
"""
|
||||||
Test whether all values are approximately equal to corresponding ones of other Table.
|
Test whether all values are approximately equal to corresponding ones of other Table.
|
||||||
|
|
||||||
|
@ -208,7 +229,7 @@ class Table:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(fname):
|
def load(fname: FileHandle) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Load from ASCII table file.
|
Load from ASCII table file.
|
||||||
|
|
||||||
|
@ -229,10 +250,7 @@ class Table:
|
||||||
Table data from file.
|
Table data from file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
f = open(fname) if isinstance(fname, (str, Path)) else fname
|
||||||
f = open(fname)
|
|
||||||
except TypeError:
|
|
||||||
f = fname
|
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
|
||||||
comments = []
|
comments = []
|
||||||
|
@ -261,7 +279,7 @@ class Table:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_ang(fname):
|
def load_ang(fname: FileHandle) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Load from ang file.
|
Load from ang file.
|
||||||
|
|
||||||
|
@ -286,10 +304,7 @@ class Table:
|
||||||
Table data from file.
|
Table data from file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
f = open(fname) if isinstance(fname, (str, Path)) else fname
|
||||||
f = open(fname)
|
|
||||||
except TypeError:
|
|
||||||
f = fname
|
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
|
||||||
content = f.readlines()
|
content = f.readlines()
|
||||||
|
@ -304,19 +319,19 @@ class Table:
|
||||||
data = np.loadtxt(content)
|
data = np.loadtxt(content)
|
||||||
|
|
||||||
shapes = {'eu':3, 'pos':2, 'IQ':1, 'CI':1, 'ID':1, 'intensity':1, 'fit':1}
|
shapes = {'eu':3, 'pos':2, 'IQ':1, 'CI':1, 'ID':1, 'intensity':1, 'fit':1}
|
||||||
remainder = data.shape[1]-sum(shapes.values())
|
if (remainder := data.shape[1]-sum(shapes.values())) > 0:
|
||||||
if remainder > 0: # 3.8 can do: if (remainder := data.shape[1]-sum(shapes.values())) > 0
|
|
||||||
shapes['unknown'] = remainder
|
shapes['unknown'] = remainder
|
||||||
|
|
||||||
return Table(data,shapes,comments)
|
return Table(data,shapes,comments)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def labels(self):
|
def labels(self) -> List[Tuple[int, ...]]:
|
||||||
return list(self.shapes)
|
return list(self.shapes)
|
||||||
|
|
||||||
|
|
||||||
def get(self,label):
|
def get(self,
|
||||||
|
label: str) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Get column data.
|
Get column data.
|
||||||
|
|
||||||
|
@ -336,7 +351,10 @@ class Table:
|
||||||
return data.astype(type(data.flatten()[0]))
|
return data.astype(type(data.flatten()[0]))
|
||||||
|
|
||||||
|
|
||||||
def set(self,label,data,info=None):
|
def set(self,
|
||||||
|
label: str,
|
||||||
|
data: np.ndarray,
|
||||||
|
info: str = None) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Set column data.
|
Set column data.
|
||||||
|
|
||||||
|
@ -357,8 +375,7 @@ class Table:
|
||||||
"""
|
"""
|
||||||
dup = self.copy()
|
dup = self.copy()
|
||||||
dup._add_comment(label, data.shape[1:], info)
|
dup._add_comment(label, data.shape[1:], info)
|
||||||
m = re.match(r'(.*)\[((\d+,)*(\d+))\]',label)
|
if m := re.match(r'(.*)\[((\d+,)*(\d+))\]',label):
|
||||||
if m:
|
|
||||||
key = m.group(1)
|
key = m.group(1)
|
||||||
idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(","))),
|
idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(","))),
|
||||||
self.shapes[key])
|
self.shapes[key])
|
||||||
|
@ -369,7 +386,10 @@ class Table:
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def add(self,label,data,info=None):
|
def add(self,
|
||||||
|
label: str,
|
||||||
|
data: np.ndarray,
|
||||||
|
info: str = None) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Add column data.
|
Add column data.
|
||||||
|
|
||||||
|
@ -401,7 +421,8 @@ class Table:
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def delete(self,label):
|
def delete(self,
|
||||||
|
label: str) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Delete column data.
|
Delete column data.
|
||||||
|
|
||||||
|
@ -422,7 +443,10 @@ class Table:
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def rename(self,old,new,info=None):
|
def rename(self,
|
||||||
|
old: Union[str, List[str]],
|
||||||
|
new: Union[str, List[str]],
|
||||||
|
info: str = None) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Rename column data.
|
Rename column data.
|
||||||
|
|
||||||
|
@ -448,7 +472,9 @@ class Table:
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def sort_by(self,labels,ascending=True):
|
def sort_by(self,
|
||||||
|
labels: Union[str, List[str]],
|
||||||
|
ascending: Union[bool, List[bool]] = True) -> 'Table':
|
||||||
"""
|
"""
|
||||||
Sort table by values of given labels.
|
Sort table by values of given labels.
|
||||||
|
|
||||||
|
@ -467,8 +493,7 @@ class Table:
|
||||||
"""
|
"""
|
||||||
labels_ = [labels] if isinstance(labels,str) else labels.copy()
|
labels_ = [labels] if isinstance(labels,str) else labels.copy()
|
||||||
for i,l in enumerate(labels_):
|
for i,l in enumerate(labels_):
|
||||||
m = re.match(r'(.*)\[((\d+,)*(\d+))\]',l)
|
if m := re.match(r'(.*)\[((\d+,)*(\d+))\]',l):
|
||||||
if m:
|
|
||||||
idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(','))),
|
idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(','))),
|
||||||
self.shapes[m.group(1)])
|
self.shapes[m.group(1)])
|
||||||
labels_[i] = f'{1+idx}_{m.group(1)}'
|
labels_[i] = f'{1+idx}_{m.group(1)}'
|
||||||
|
@ -481,7 +506,8 @@ class Table:
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def append(self,other):
|
def append(self,
|
||||||
|
other: 'Table') -> 'Table':
|
||||||
"""
|
"""
|
||||||
Append other table vertically (similar to numpy.vstack).
|
Append other table vertically (similar to numpy.vstack).
|
||||||
|
|
||||||
|
@ -500,13 +526,14 @@ class Table:
|
||||||
"""
|
"""
|
||||||
if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns):
|
if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns):
|
||||||
raise KeyError('Labels or shapes or order do not match')
|
raise KeyError('Labels or shapes or order do not match')
|
||||||
else:
|
|
||||||
dup = self.copy()
|
dup = self.copy()
|
||||||
dup.data = dup.data.append(other.data,ignore_index=True)
|
dup.data = dup.data.append(other.data,ignore_index=True)
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def join(self,other):
|
def join(self,
|
||||||
|
other: 'Table') -> 'Table':
|
||||||
"""
|
"""
|
||||||
Append other table horizontally (similar to numpy.hstack).
|
Append other table horizontally (similar to numpy.hstack).
|
||||||
|
|
||||||
|
@ -525,7 +552,7 @@ class Table:
|
||||||
"""
|
"""
|
||||||
if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]:
|
if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]:
|
||||||
raise KeyError('Duplicated keys or row count mismatch')
|
raise KeyError('Duplicated keys or row count mismatch')
|
||||||
else:
|
|
||||||
dup = self.copy()
|
dup = self.copy()
|
||||||
dup.data = dup.data.join(other.data)
|
dup.data = dup.data.join(other.data)
|
||||||
for key in other.shapes:
|
for key in other.shapes:
|
||||||
|
@ -533,7 +560,8 @@ class Table:
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
|
|
||||||
def save(self,fname):
|
def save(self,
|
||||||
|
fname: FileHandle):
|
||||||
"""
|
"""
|
||||||
Save as plain text file.
|
Save as plain text file.
|
||||||
|
|
||||||
|
@ -543,9 +571,8 @@ class Table:
|
||||||
Filename or file for writing.
|
Filename or file for writing.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
seen = set()
|
|
||||||
labels = []
|
labels = []
|
||||||
for l in [x for x in self.data.columns if not (x in seen or seen.add(x))]:
|
for l in list(dict.fromkeys(self.data.columns)):
|
||||||
if self.shapes[l] == (1,):
|
if self.shapes[l] == (1,):
|
||||||
labels.append(f'{l}')
|
labels.append(f'{l}')
|
||||||
elif len(self.shapes[l]) == 1:
|
elif len(self.shapes[l]) == 1:
|
||||||
|
@ -555,10 +582,7 @@ class Table:
|
||||||
labels += [f'{util.srepr(self.shapes[l],"x")}:{i+1}_{l}' \
|
labels += [f'{util.srepr(self.shapes[l],"x")}:{i+1}_{l}' \
|
||||||
for i in range(np.prod(self.shapes[l]))]
|
for i in range(np.prod(self.shapes[l]))]
|
||||||
|
|
||||||
try:
|
f = open(fname,'w',newline='\n') if isinstance(fname, (str, Path)) else fname
|
||||||
fhandle = open(fname,'w',newline='\n')
|
|
||||||
except TypeError:
|
|
||||||
fhandle = fname
|
|
||||||
|
|
||||||
fhandle.write('\n'.join([f'# {c}' for c in self.comments] + [' '.join(labels)])+'\n')
|
f.write('\n'.join([f'# {c}' for c in self.comments] + [' '.join(labels)])+'\n')
|
||||||
self.data.to_csv(fhandle,sep=' ',na_rep='nan',index=False,header=False)
|
self.data.to_csv(f,sep=' ',na_rep='nan',index=False,header=False)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
"""Functionality for typehints."""
|
||||||
|
|
||||||
|
from typing import Sequence, Union, TextIO
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
FloatSequence = Union[np.ndarray,Sequence[float]]
|
||||||
|
IntSequence = Union[np.ndarray,Sequence[int]]
|
||||||
|
FileHandle = Union[TextIO, str, Path]
|
|
@ -2,6 +2,7 @@ import os
|
||||||
import warnings
|
import warnings
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Union, Literal, List
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import vtk
|
import vtk
|
||||||
|
@ -9,6 +10,7 @@ from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk
|
||||||
from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray
|
from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray
|
||||||
from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np
|
from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np
|
||||||
|
|
||||||
|
from ._typehints import FloatSequence, IntSequence
|
||||||
from . import util
|
from . import util
|
||||||
from . import Table
|
from . import Table
|
||||||
|
|
||||||
|
@ -20,7 +22,8 @@ class VTK:
|
||||||
High-level interface to VTK.
|
High-level interface to VTK.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,vtk_data):
|
def __init__(self,
|
||||||
|
vtk_data: vtk.vtkDataSet):
|
||||||
"""
|
"""
|
||||||
New spatial visualization.
|
New spatial visualization.
|
||||||
|
|
||||||
|
@ -28,15 +31,17 @@ class VTK:
|
||||||
----------
|
----------
|
||||||
vtk_data : subclass of vtk.vtkDataSet
|
vtk_data : subclass of vtk.vtkDataSet
|
||||||
Description of geometry and topology, optionally with attached data.
|
Description of geometry and topology, optionally with attached data.
|
||||||
Valid types are vtk.vtkRectilinearGrid, vtk.vtkUnstructuredGrid,
|
Valid types are vtk.vtkImageData, vtk.vtkUnstructuredGrid,
|
||||||
or vtk.vtkPolyData.
|
vtk.vtkPolyData, and vtk.vtkRectilinearGrid.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.vtk_data = vtk_data
|
self.vtk_data = vtk_data
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_image_data(cells,size,origin=np.zeros(3)):
|
def from_image_data(cells: IntSequence,
|
||||||
|
size: FloatSequence,
|
||||||
|
origin: FloatSequence = np.zeros(3)) -> 'VTK':
|
||||||
"""
|
"""
|
||||||
Create VTK of type vtk.vtkImageData.
|
Create VTK of type vtk.vtkImageData.
|
||||||
|
|
||||||
|
@ -60,13 +65,15 @@ class VTK:
|
||||||
vtk_data = vtk.vtkImageData()
|
vtk_data = vtk.vtkImageData()
|
||||||
vtk_data.SetDimensions(*(np.array(cells)+1))
|
vtk_data.SetDimensions(*(np.array(cells)+1))
|
||||||
vtk_data.SetOrigin(*(np.array(origin)))
|
vtk_data.SetOrigin(*(np.array(origin)))
|
||||||
vtk_data.SetSpacing(*(size/cells))
|
vtk_data.SetSpacing(*(np.array(size)/np.array(cells)))
|
||||||
|
|
||||||
return VTK(vtk_data)
|
return VTK(vtk_data)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_rectilinear_grid(grid,size,origin=np.zeros(3)):
|
def from_rectilinear_grid(grid: np.ndarray,
|
||||||
|
size: FloatSequence,
|
||||||
|
origin: FloatSequence = np.zeros(3)) -> 'VTK':
|
||||||
"""
|
"""
|
||||||
Create VTK of type vtk.vtkRectilinearGrid.
|
Create VTK of type vtk.vtkRectilinearGrid.
|
||||||
|
|
||||||
|
@ -98,7 +105,9 @@ class VTK:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_unstructured_grid(nodes,connectivity,cell_type):
|
def from_unstructured_grid(nodes: np.ndarray,
|
||||||
|
connectivity: np.ndarray,
|
||||||
|
cell_type: str) -> 'VTK':
|
||||||
"""
|
"""
|
||||||
Create VTK of type vtk.vtkUnstructuredGrid.
|
Create VTK of type vtk.vtkUnstructuredGrid.
|
||||||
|
|
||||||
|
@ -138,7 +147,7 @@ class VTK:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_poly_data(points):
|
def from_poly_data(points: np.ndarray) -> 'VTK':
|
||||||
"""
|
"""
|
||||||
Create VTK of type vtk.polyData.
|
Create VTK of type vtk.polyData.
|
||||||
|
|
||||||
|
@ -172,15 +181,17 @@ class VTK:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(fname,dataset_type=None):
|
def load(fname: Union[str, Path],
|
||||||
|
dataset_type: Literal['ImageData', 'UnstructuredGrid', 'PolyData'] = None) -> 'VTK':
|
||||||
"""
|
"""
|
||||||
Load from VTK file.
|
Load from VTK file.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
fname : str or pathlib.Path
|
fname : str or pathlib.Path
|
||||||
Filename for reading. Valid extensions are .vti, .vtr, .vtu, .vtp, and .vtk.
|
Filename for reading.
|
||||||
dataset_type : {'vtkImageData', ''vtkRectilinearGrid', 'vtkUnstructuredGrid', 'vtkPolyData'}, optional
|
Valid extensions are .vti, .vtr, .vtu, .vtp, and .vtk.
|
||||||
|
dataset_type : {'ImageData', 'UnstructuredGrid', 'PolyData'}, optional
|
||||||
Name of the vtk.vtkDataSet subclass when opening a .vtk file.
|
Name of the vtk.vtkDataSet subclass when opening a .vtk file.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -191,8 +202,7 @@ class VTK:
|
||||||
"""
|
"""
|
||||||
if not os.path.isfile(fname): # vtk has a strange error handling
|
if not os.path.isfile(fname): # vtk has a strange error handling
|
||||||
raise FileNotFoundError(f'No such file: {fname}')
|
raise FileNotFoundError(f'No such file: {fname}')
|
||||||
ext = Path(fname).suffix
|
if (ext := Path(fname).suffix) == '.vtk' or dataset_type is not None:
|
||||||
if ext == '.vtk' or dataset_type is not None:
|
|
||||||
reader = vtk.vtkGenericDataObjectReader()
|
reader = vtk.vtkGenericDataObjectReader()
|
||||||
reader.SetFileName(str(fname))
|
reader.SetFileName(str(fname))
|
||||||
if dataset_type is None:
|
if dataset_type is None:
|
||||||
|
@ -234,7 +244,11 @@ class VTK:
|
||||||
def _write(writer):
|
def _write(writer):
|
||||||
"""Wrapper for parallel writing."""
|
"""Wrapper for parallel writing."""
|
||||||
writer.Write()
|
writer.Write()
|
||||||
def save(self,fname,parallel=True,compress=True):
|
|
||||||
|
def save(self,
|
||||||
|
fname: Union[str, Path],
|
||||||
|
parallel: bool = True,
|
||||||
|
compress: bool = True):
|
||||||
"""
|
"""
|
||||||
Save as VTK file.
|
Save as VTK file.
|
||||||
|
|
||||||
|
@ -242,7 +256,7 @@ class VTK:
|
||||||
----------
|
----------
|
||||||
fname : str or pathlib.Path
|
fname : str or pathlib.Path
|
||||||
Filename for writing.
|
Filename for writing.
|
||||||
parallel : boolean, optional
|
parallel : bool, optional
|
||||||
Write data in parallel background process. Defaults to True.
|
Write data in parallel background process. Defaults to True.
|
||||||
compress : bool, optional
|
compress : bool, optional
|
||||||
Compress with zlib algorithm. Defaults to True.
|
Compress with zlib algorithm. Defaults to True.
|
||||||
|
@ -280,7 +294,9 @@ class VTK:
|
||||||
|
|
||||||
# Check https://blog.kitware.com/ghost-and-blanking-visibility-changes/ for missing data
|
# Check https://blog.kitware.com/ghost-and-blanking-visibility-changes/ for missing data
|
||||||
# Needs support for damask.Table
|
# Needs support for damask.Table
|
||||||
def add(self,data,label=None):
|
def add(self,
|
||||||
|
data: Union[np.ndarray, np.ma.MaskedArray],
|
||||||
|
label: str = None):
|
||||||
"""
|
"""
|
||||||
Add data to either cells or points.
|
Add data to either cells or points.
|
||||||
|
|
||||||
|
@ -327,7 +343,8 @@ class VTK:
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
|
|
||||||
def get(self,label):
|
def get(self,
|
||||||
|
label: str) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Get either cell or point data.
|
Get either cell or point data.
|
||||||
|
|
||||||
|
@ -369,7 +386,7 @@ class VTK:
|
||||||
raise ValueError(f'Array "{label}" not found.')
|
raise ValueError(f'Array "{label}" not found.')
|
||||||
|
|
||||||
|
|
||||||
def get_comments(self):
|
def get_comments(self) -> List[str]:
|
||||||
"""Return the comments."""
|
"""Return the comments."""
|
||||||
fielddata = self.vtk_data.GetFieldData()
|
fielddata = self.vtk_data.GetFieldData()
|
||||||
for a in range(fielddata.GetNumberOfArrays()):
|
for a in range(fielddata.GetNumberOfArrays()):
|
||||||
|
@ -379,7 +396,8 @@ class VTK:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def set_comments(self,comments):
|
def set_comments(self,
|
||||||
|
comments: Union[str, List[str]]):
|
||||||
"""
|
"""
|
||||||
Set comments.
|
Set comments.
|
||||||
|
|
||||||
|
@ -396,7 +414,8 @@ class VTK:
|
||||||
self.vtk_data.GetFieldData().AddArray(s)
|
self.vtk_data.GetFieldData().AddArray(s)
|
||||||
|
|
||||||
|
|
||||||
def add_comments(self,comments):
|
def add_comments(self,
|
||||||
|
comments: Union[str, List[str]]):
|
||||||
"""
|
"""
|
||||||
Add comments.
|
Add comments.
|
||||||
|
|
||||||
|
@ -409,7 +428,7 @@ class VTK:
|
||||||
self.set_comments(self.get_comments() + ([comments] if isinstance(comments,str) else comments))
|
self.set_comments(self.get_comments() + ([comments] if isinstance(comments,str) else comments))
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
"""ASCII representation of the VTK data."""
|
"""ASCII representation of the VTK data."""
|
||||||
writer = vtk.vtkDataSetWriter()
|
writer = vtk.vtkDataSetWriter()
|
||||||
writer.SetHeader(f'# {util.execution_stamp("VTK")}')
|
writer.SetHeader(f'# {util.execution_stamp("VTK")}')
|
||||||
|
@ -436,28 +455,30 @@ class VTK:
|
||||||
width = tk.winfo_screenwidth()
|
width = tk.winfo_screenwidth()
|
||||||
height = tk.winfo_screenheight()
|
height = tk.winfo_screenheight()
|
||||||
tk.destroy()
|
tk.destroy()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
width = 1024
|
width = 1024
|
||||||
height = 768
|
height = 768
|
||||||
|
|
||||||
mapper = vtk.vtkDataSetMapper()
|
mapper = vtk.vtkDataSetMapper()
|
||||||
mapper.SetInputData(self.vtk_data)
|
mapper.SetInputData(self.vtk_data)
|
||||||
|
|
||||||
actor = vtk.vtkActor()
|
actor = vtk.vtkActor()
|
||||||
actor.SetMapper(mapper)
|
actor.SetMapper(mapper)
|
||||||
|
actor.GetProperty().SetColor(230/255,150/255,68/255)
|
||||||
|
|
||||||
ren = vtk.vtkRenderer()
|
ren = vtk.vtkRenderer()
|
||||||
|
ren.AddActor(actor)
|
||||||
|
ren.SetBackground(67/255,128/255,208/255)
|
||||||
|
|
||||||
window = vtk.vtkRenderWindow()
|
window = vtk.vtkRenderWindow()
|
||||||
window.AddRenderer(ren)
|
window.AddRenderer(ren)
|
||||||
|
|
||||||
ren.AddActor(actor)
|
|
||||||
ren.SetBackground(0.2,0.2,0.2)
|
|
||||||
|
|
||||||
window.SetSize(width,height)
|
window.SetSize(width,height)
|
||||||
|
window.SetWindowName(util.execution_stamp('VTK','show'))
|
||||||
|
|
||||||
iren = vtk.vtkRenderWindowInteractor()
|
iren = vtk.vtkRenderWindowInteractor()
|
||||||
iren.SetRenderWindow(window)
|
iren.SetRenderWindow(window)
|
||||||
|
if os.name == 'posix' and 'DISPLAY' not in os.environ:
|
||||||
iren.Initialize()
|
print('Found no rendering device')
|
||||||
|
else:
|
||||||
window.Render()
|
window.Render()
|
||||||
iren.Start()
|
iren.Start()
|
||||||
|
|
|
@ -12,21 +12,25 @@ the following operations are required for tensorial data:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Tuple, Union
|
from typing import Tuple as _Tuple
|
||||||
|
|
||||||
from scipy import spatial as _spatial
|
from scipy import spatial as _spatial
|
||||||
import numpy as _np
|
import numpy as _np
|
||||||
|
|
||||||
|
from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence
|
||||||
|
|
||||||
def _ks(size: _np.ndarray, cells: Union[_np.ndarray,Sequence[int]], first_order: bool = False) -> _np.ndarray:
|
|
||||||
|
def _ks(size: _FloatSequence,
|
||||||
|
cells: _IntSequence,
|
||||||
|
first_order: bool = False) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Get wave numbers operator.
|
Get wave numbers operator.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
cells : numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Number of cells.
|
Number of cells.
|
||||||
first_order : bool, optional
|
first_order : bool, optional
|
||||||
Correction for first order derivatives, defaults to False.
|
Correction for first order derivatives, defaults to False.
|
||||||
|
@ -45,20 +49,21 @@ def _ks(size: _np.ndarray, cells: Union[_np.ndarray,Sequence[int]], first_order:
|
||||||
return _np.stack(_np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij'), axis=-1)
|
return _np.stack(_np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij'), axis=-1)
|
||||||
|
|
||||||
|
|
||||||
def curl(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
|
def curl(size: _FloatSequence,
|
||||||
|
f: _np.ndarray) -> _np.ndarray:
|
||||||
u"""
|
u"""
|
||||||
Calculate curl of a vector or tensor field in Fourier space.
|
Calculate curl of a vector or tensor field in Fourier space.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
f : numpy.ndarray of shape (:,:,:,3) or (:,:,:,3,3)
|
f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
|
||||||
Periodic field of which the curl is calculated.
|
Periodic field of which the curl is calculated.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
∇ × f : numpy.ndarray
|
∇ × f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
|
||||||
Curl of f.
|
Curl of f.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -76,20 +81,21 @@ def curl(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
|
||||||
return _np.fft.irfftn(curl_,axes=(0,1,2),s=f.shape[:3])
|
return _np.fft.irfftn(curl_,axes=(0,1,2),s=f.shape[:3])
|
||||||
|
|
||||||
|
|
||||||
def divergence(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
|
def divergence(size: _FloatSequence,
|
||||||
|
f: _np.ndarray) -> _np.ndarray:
|
||||||
u"""
|
u"""
|
||||||
Calculate divergence of a vector or tensor field in Fourier space.
|
Calculate divergence of a vector or tensor field in Fourier space.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
f : numpy.ndarray of shape (:,:,:,3) or (:,:,:,3,3)
|
f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
|
||||||
Periodic field of which the divergence is calculated.
|
Periodic field of which the divergence is calculated.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
∇ · f : numpy.ndarray
|
∇ · f : numpy.ndarray, shape (:,:,:,1) or (:,:,:,3)
|
||||||
Divergence of f.
|
Divergence of f.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -103,20 +109,21 @@ def divergence(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
|
||||||
return _np.fft.irfftn(div_,axes=(0,1,2),s=f.shape[:3])
|
return _np.fft.irfftn(div_,axes=(0,1,2),s=f.shape[:3])
|
||||||
|
|
||||||
|
|
||||||
def gradient(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
|
def gradient(size: _FloatSequence,
|
||||||
|
f: _np.ndarray) -> _np.ndarray:
|
||||||
u"""
|
u"""
|
||||||
Calculate gradient of a scalar or vector field in Fourier space.
|
Calculate gradient of a scalar or vector field in Fourier space.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
f : numpy.ndarray of shape (:,:,:,1) or (:,:,:,3)
|
f : numpy.ndarray, shape (:,:,:,1) or (:,:,:,3)
|
||||||
Periodic field of which the gradient is calculated.
|
Periodic field of which the gradient is calculated.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
∇ f : numpy.ndarray
|
∇ f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
|
||||||
Divergence of f.
|
Divergence of f.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -130,29 +137,30 @@ def gradient(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
|
||||||
return _np.fft.irfftn(grad_,axes=(0,1,2),s=f.shape[:3])
|
return _np.fft.irfftn(grad_,axes=(0,1,2),s=f.shape[:3])
|
||||||
|
|
||||||
|
|
||||||
def coordinates0_point(cells: Union[ _np.ndarray,Sequence[int]],
|
def coordinates0_point(cells: _IntSequence,
|
||||||
size: _np.ndarray,
|
size: _FloatSequence,
|
||||||
origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray:
|
origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Cell center positions (undeformed).
|
Cell center positions (undeformed).
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cells : numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Number of cells.
|
Number of cells.
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
origin : numpy.ndarray, optional
|
origin : sequence of float, len(3), optional
|
||||||
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
x_p_0 : numpy.ndarray
|
x_p_0 : numpy.ndarray, shape (:,:,:,3)
|
||||||
Undeformed cell center coordinates.
|
Undeformed cell center coordinates.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
start = origin + size/_np.array(cells)*.5
|
size_ = _np.array(size,float)
|
||||||
end = origin + size - size/_np.array(cells)*.5
|
start = origin + size_/_np.array(cells,int)*.5
|
||||||
|
end = origin + size_ - size_/_np.array(cells,int)*.5
|
||||||
|
|
||||||
return _np.stack(_np.meshgrid(_np.linspace(start[0],end[0],cells[0]),
|
return _np.stack(_np.meshgrid(_np.linspace(start[0],end[0],cells[0]),
|
||||||
_np.linspace(start[1],end[1],cells[1]),
|
_np.linspace(start[1],end[1],cells[1]),
|
||||||
|
@ -160,24 +168,25 @@ def coordinates0_point(cells: Union[ _np.ndarray,Sequence[int]],
|
||||||
axis = -1)
|
axis = -1)
|
||||||
|
|
||||||
|
|
||||||
def displacement_fluct_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def displacement_fluct_point(size: _FloatSequence,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Cell center displacement field from fluctuation part of the deformation gradient field.
|
Cell center displacement field from fluctuation part of the deformation gradient field.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
u_p_fluct : numpy.ndarray
|
u_p_fluct : numpy.ndarray, shape (:,:,:,3)
|
||||||
Fluctuating part of the cell center displacements.
|
Fluctuating part of the cell center displacements.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
integrator = 0.5j*size/_np.pi
|
integrator = 0.5j*_np.array(size,float)/_np.pi
|
||||||
|
|
||||||
k_s = _ks(size,F.shape[:3],False)
|
k_s = _ks(size,F.shape[:3],False)
|
||||||
k_s_squared = _np.einsum('...l,...l',k_s,k_s)
|
k_s_squared = _np.einsum('...l,...l',k_s,k_s)
|
||||||
|
@ -192,20 +201,21 @@ def displacement_fluct_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
||||||
return _np.fft.irfftn(displacement,axes=(0,1,2),s=F.shape[:3])
|
return _np.fft.irfftn(displacement,axes=(0,1,2),s=F.shape[:3])
|
||||||
|
|
||||||
|
|
||||||
def displacement_avg_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def displacement_avg_point(size: _FloatSequence,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Cell center displacement field from average part of the deformation gradient field.
|
Cell center displacement field from average part of the deformation gradient field.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
u_p_avg : numpy.ndarray
|
u_p_avg : numpy.ndarray, shape (:,:,:,3)
|
||||||
Average part of the cell center displacements.
|
Average part of the cell center displacements.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -213,42 +223,45 @@ def displacement_avg_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
||||||
return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_point(F.shape[:3],size))
|
return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_point(F.shape[:3],size))
|
||||||
|
|
||||||
|
|
||||||
def displacement_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def displacement_point(size: _FloatSequence,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Cell center displacement field from deformation gradient field.
|
Cell center displacement field from deformation gradient field.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
u_p : numpy.ndarray
|
u_p : numpy.ndarray, shape (:,:,:,3)
|
||||||
Cell center displacements.
|
Cell center displacements.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return displacement_avg_point(size,F) + displacement_fluct_point(size,F)
|
return displacement_avg_point(size,F) + displacement_fluct_point(size,F)
|
||||||
|
|
||||||
|
|
||||||
def coordinates_point(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray:
|
def coordinates_point(size: _FloatSequence,
|
||||||
|
F: _np.ndarray,
|
||||||
|
origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Cell center positions.
|
Cell center positions.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
origin : numpy.ndarray of shape (3), optional
|
origin : sequence of float, len(3), optional
|
||||||
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
x_p : numpy.ndarray
|
x_p : numpy.ndarray, shape (:,:,:,3)
|
||||||
Cell center coordinates.
|
Cell center coordinates.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -256,14 +269,14 @@ def coordinates_point(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _
|
||||||
|
|
||||||
|
|
||||||
def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray,
|
def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray,
|
||||||
ordered: bool = True) -> Tuple[_np.ndarray,_np.ndarray,_np.ndarray]:
|
ordered: bool = True) -> _Tuple[_np.ndarray,_np.ndarray,_np.ndarray]:
|
||||||
"""
|
"""
|
||||||
Return grid 'DNA', i.e. cells, size, and origin from 1D array of point positions.
|
Return grid 'DNA', i.e. cells, size, and origin from 1D array of point positions.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
coordinates0 : numpy.ndarray of shape (:,3)
|
coordinates0 : numpy.ndarray, shape (:,3)
|
||||||
Undeformed cell coordinates.
|
Undeformed cell center coordinates.
|
||||||
ordered : bool, optional
|
ordered : bool, optional
|
||||||
Expect coordinates0 data to be ordered (x fast, z slow).
|
Expect coordinates0 data to be ordered (x fast, z slow).
|
||||||
Defaults to True.
|
Defaults to True.
|
||||||
|
@ -277,7 +290,7 @@ def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray,
|
||||||
coords = [_np.unique(coordinates0[:,i]) for i in range(3)]
|
coords = [_np.unique(coordinates0[:,i]) for i in range(3)]
|
||||||
mincorner = _np.array(list(map(min,coords)))
|
mincorner = _np.array(list(map(min,coords)))
|
||||||
maxcorner = _np.array(list(map(max,coords)))
|
maxcorner = _np.array(list(map(max,coords)))
|
||||||
cells = _np.array(list(map(len,coords)),'i')
|
cells = _np.array(list(map(len,coords)),int)
|
||||||
size = cells/_np.maximum(cells-1,1) * (maxcorner-mincorner)
|
size = cells/_np.maximum(cells-1,1) * (maxcorner-mincorner)
|
||||||
delta = size/cells
|
delta = size/cells
|
||||||
origin = mincorner - delta*.5
|
origin = mincorner - delta*.5
|
||||||
|
@ -305,24 +318,24 @@ def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray,
|
||||||
return (cells,size,origin)
|
return (cells,size,origin)
|
||||||
|
|
||||||
|
|
||||||
def coordinates0_node(cells: Union[_np.ndarray,Sequence[int]],
|
def coordinates0_node(cells: _IntSequence,
|
||||||
size: _np.ndarray,
|
size: _FloatSequence,
|
||||||
origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray:
|
origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Nodal positions (undeformed).
|
Nodal positions (undeformed).
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cells : numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Number of cells.
|
Number of cells.
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
origin : numpy.ndarray of shape (3), optional
|
origin : sequence of float, len(3), optional
|
||||||
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
x_n_0 : numpy.ndarray
|
x_n_0 : numpy.ndarray, shape (:,:,:,3)
|
||||||
Undeformed nodal coordinates.
|
Undeformed nodal coordinates.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -332,40 +345,42 @@ def coordinates0_node(cells: Union[_np.ndarray,Sequence[int]],
|
||||||
axis = -1)
|
axis = -1)
|
||||||
|
|
||||||
|
|
||||||
def displacement_fluct_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def displacement_fluct_node(size: _FloatSequence,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Nodal displacement field from fluctuation part of the deformation gradient field.
|
Nodal displacement field from fluctuation part of the deformation gradient field.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
u_n_fluct : numpy.ndarray
|
u_n_fluct : numpy.ndarray, shape (:,:,:,3)
|
||||||
Fluctuating part of the nodal displacements.
|
Fluctuating part of the nodal displacements.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return point_to_node(displacement_fluct_point(size,F))
|
return point_to_node(displacement_fluct_point(size,F))
|
||||||
|
|
||||||
|
|
||||||
def displacement_avg_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def displacement_avg_node(size: _FloatSequence,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Nodal displacement field from average part of the deformation gradient field.
|
Nodal displacement field from average part of the deformation gradient field.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
u_n_avg : numpy.ndarray
|
u_n_avg : numpy.ndarray, shape (:,:,:,3)
|
||||||
Average part of the nodal displacements.
|
Average part of the nodal displacements.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -373,42 +388,45 @@ def displacement_avg_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
||||||
return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_node(F.shape[:3],size))
|
return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_node(F.shape[:3],size))
|
||||||
|
|
||||||
|
|
||||||
def displacement_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def displacement_node(size: _FloatSequence,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Nodal displacement field from deformation gradient field.
|
Nodal displacement field from deformation gradient field.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
u_p : numpy.ndarray
|
u_p : numpy.ndarray, shape (:,:,:,3)
|
||||||
Nodal displacements.
|
Nodal displacements.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return displacement_avg_node(size,F) + displacement_fluct_node(size,F)
|
return displacement_avg_node(size,F) + displacement_fluct_node(size,F)
|
||||||
|
|
||||||
|
|
||||||
def coordinates_node(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray:
|
def coordinates_node(size: _FloatSequence,
|
||||||
|
F: _np.ndarray,
|
||||||
|
origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Nodal positions.
|
Nodal positions.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the periodic field.
|
Physical size of the periodic field.
|
||||||
F : numpy.ndarray
|
F : numpy.ndarray, shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
origin : numpy.ndarray of shape (3), optional
|
origin : sequence of float, len(3), optional
|
||||||
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
x_n : numpy.ndarray
|
x_n : numpy.ndarray, shape (:,:,:,3)
|
||||||
Nodal coordinates.
|
Nodal coordinates.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -416,13 +434,13 @@ def coordinates_node(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _n
|
||||||
|
|
||||||
|
|
||||||
def cellsSizeOrigin_coordinates0_node(coordinates0: _np.ndarray,
|
def cellsSizeOrigin_coordinates0_node(coordinates0: _np.ndarray,
|
||||||
ordered: bool = True) -> Tuple[_np.ndarray,_np.ndarray,_np.ndarray]:
|
ordered: bool = True) -> _Tuple[_np.ndarray,_np.ndarray,_np.ndarray]:
|
||||||
"""
|
"""
|
||||||
Return grid 'DNA', i.e. cells, size, and origin from 1D array of nodal positions.
|
Return grid 'DNA', i.e. cells, size, and origin from 1D array of nodal positions.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
coordinates0 : numpy.ndarray of shape (:,3)
|
coordinates0 : numpy.ndarray, shape (:,3)
|
||||||
Undeformed nodal coordinates.
|
Undeformed nodal coordinates.
|
||||||
ordered : bool, optional
|
ordered : bool, optional
|
||||||
Expect coordinates0 data to be ordered (x fast, z slow).
|
Expect coordinates0 data to be ordered (x fast, z slow).
|
||||||
|
@ -437,7 +455,7 @@ def cellsSizeOrigin_coordinates0_node(coordinates0: _np.ndarray,
|
||||||
coords = [_np.unique(coordinates0[:,i]) for i in range(3)]
|
coords = [_np.unique(coordinates0[:,i]) for i in range(3)]
|
||||||
mincorner = _np.array(list(map(min,coords)))
|
mincorner = _np.array(list(map(min,coords)))
|
||||||
maxcorner = _np.array(list(map(max,coords)))
|
maxcorner = _np.array(list(map(max,coords)))
|
||||||
cells = _np.array(list(map(len,coords)),'i') - 1
|
cells = _np.array(list(map(len,coords)),int) - 1
|
||||||
size = maxcorner-mincorner
|
size = maxcorner-mincorner
|
||||||
origin = mincorner
|
origin = mincorner
|
||||||
|
|
||||||
|
@ -463,12 +481,12 @@ def point_to_node(cell_data: _np.ndarray) -> _np.ndarray:
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
cell_data : numpy.ndarray of shape (:,:,:,...)
|
cell_data : numpy.ndarray, shape (:,:,:,...)
|
||||||
Data defined on the cell centers of a periodic grid.
|
Data defined on the cell centers of a periodic grid.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
node_data : numpy.ndarray of shape (:,:,:,...)
|
node_data : numpy.ndarray, shape (:,:,:,...)
|
||||||
Data defined on the nodes of a periodic grid.
|
Data defined on the nodes of a periodic grid.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -485,12 +503,12 @@ def node_to_point(node_data: _np.ndarray) -> _np.ndarray:
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
node_data : numpy.ndarray of shape (:,:,:,...)
|
node_data : numpy.ndarray, shape (:,:,:,...)
|
||||||
Data defined on the nodes of a periodic grid.
|
Data defined on the nodes of a periodic grid.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
cell_data : numpy.ndarray of shape (:,:,:,...)
|
cell_data : numpy.ndarray, shape (:,:,:,...)
|
||||||
Data defined on the cell centers of a periodic grid.
|
Data defined on the cell centers of a periodic grid.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -507,7 +525,7 @@ def coordinates0_valid(coordinates0: _np.ndarray) -> bool:
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
coordinates0 : numpy.ndarray
|
coordinates0 : numpy.ndarray, shape (:,3)
|
||||||
Array of undeformed cell coordinates.
|
Array of undeformed cell coordinates.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -523,17 +541,19 @@ def coordinates0_valid(coordinates0: _np.ndarray) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def regrid(size: _np.ndarray, F: _np.ndarray, cells: Union[_np.ndarray,Sequence[int]]) -> _np.ndarray:
|
def regrid(size: _FloatSequence,
|
||||||
|
F: _np.ndarray,
|
||||||
|
cells: _IntSequence) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Return mapping from coordinates in deformed configuration to a regular grid.
|
Return mapping from coordinates in deformed configuration to a regular grid.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size.
|
Physical size.
|
||||||
F : numpy.ndarray of shape (:,:,:,3,3)
|
F : numpy.ndarray, shape (:,:,:,3,3), shape (:,:,:,3,3)
|
||||||
Deformation gradient field.
|
Deformation gradient field.
|
||||||
cells : numpy.ndarray of shape (3)
|
cells : sequence of int, len (3)
|
||||||
Cell count along x,y,z of remapping grid.
|
Cell count along x,y,z of remapping grid.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,7 +5,7 @@ All routines operate on numpy.ndarrays of shape (...,3,3).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence
|
from typing import Sequence as _Sequence
|
||||||
|
|
||||||
import numpy as _np
|
import numpy as _np
|
||||||
|
|
||||||
|
@ -122,7 +122,9 @@ def rotation(T: _np.ndarray) -> _rotation.Rotation:
|
||||||
return _rotation.Rotation.from_matrix(_polar_decomposition(T,'R')[0])
|
return _rotation.Rotation.from_matrix(_polar_decomposition(T,'R')[0])
|
||||||
|
|
||||||
|
|
||||||
def strain(F: _np.ndarray, t: str, m: float) -> _np.ndarray:
|
def strain(F: _np.ndarray,
|
||||||
|
t: str,
|
||||||
|
m: float) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Calculate strain tensor (Seth–Hill family).
|
Calculate strain tensor (Seth–Hill family).
|
||||||
|
|
||||||
|
@ -162,7 +164,8 @@ def strain(F: _np.ndarray, t: str, m: float) -> _np.ndarray:
|
||||||
return eps
|
return eps
|
||||||
|
|
||||||
|
|
||||||
def stress_Cauchy(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def stress_Cauchy(P: _np.ndarray,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Calculate the Cauchy stress (true stress).
|
Calculate the Cauchy stress (true stress).
|
||||||
|
|
||||||
|
@ -184,7 +187,8 @@ def stress_Cauchy(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
||||||
return _tensor.symmetric(_np.einsum('...,...ij,...kj',1.0/_np.linalg.det(F),P,F))
|
return _tensor.symmetric(_np.einsum('...,...ij,...kj',1.0/_np.linalg.det(F),P,F))
|
||||||
|
|
||||||
|
|
||||||
def stress_second_Piola_Kirchhoff(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
|
def stress_second_Piola_Kirchhoff(P: _np.ndarray,
|
||||||
|
F: _np.ndarray) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Calculate the second Piola-Kirchhoff stress.
|
Calculate the second Piola-Kirchhoff stress.
|
||||||
|
|
||||||
|
@ -243,7 +247,8 @@ def stretch_right(T: _np.ndarray) -> _np.ndarray:
|
||||||
return _polar_decomposition(T,'U')[0]
|
return _polar_decomposition(T,'U')[0]
|
||||||
|
|
||||||
|
|
||||||
def _polar_decomposition(T: _np.ndarray, requested: Sequence[str]) -> tuple:
|
def _polar_decomposition(T: _np.ndarray,
|
||||||
|
requested: _Sequence[str]) -> tuple:
|
||||||
"""
|
"""
|
||||||
Perform singular value decomposition.
|
Perform singular value decomposition.
|
||||||
|
|
||||||
|
@ -251,7 +256,7 @@ def _polar_decomposition(T: _np.ndarray, requested: Sequence[str]) -> tuple:
|
||||||
----------
|
----------
|
||||||
T : numpy.ndarray, shape (...,3,3)
|
T : numpy.ndarray, shape (...,3,3)
|
||||||
Tensor of which the singular values are computed.
|
Tensor of which the singular values are computed.
|
||||||
requested : iterable of str
|
requested : sequence of {'R', 'U', 'V'}
|
||||||
Requested outputs: ‘R’ for the rotation tensor,
|
Requested outputs: ‘R’ for the rotation tensor,
|
||||||
‘V’ for left stretch tensor and ‘U’ for right stretch tensor.
|
‘V’ for left stretch tensor and ‘U’ for right stretch tensor.
|
||||||
|
|
||||||
|
@ -273,7 +278,8 @@ def _polar_decomposition(T: _np.ndarray, requested: Sequence[str]) -> tuple:
|
||||||
return tuple(output)
|
return tuple(output)
|
||||||
|
|
||||||
|
|
||||||
def _equivalent_Mises(T_sym: _np.ndarray, s: float) -> _np.ndarray:
|
def _equivalent_Mises(T_sym: _np.ndarray,
|
||||||
|
s: float) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Base equation for Mises equivalent of a stress or strain tensor.
|
Base equation for Mises equivalent of a stress or strain tensor.
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,29 @@
|
||||||
"""Functionality for generation of seed points for Voronoi or Laguerre tessellation."""
|
"""Functionality for generation of seed points for Voronoi or Laguerre tessellation."""
|
||||||
|
|
||||||
from typing import Sequence,Tuple
|
from typing import Tuple as _Tuple
|
||||||
|
|
||||||
from scipy import spatial as _spatial
|
from scipy import spatial as _spatial
|
||||||
import numpy as _np
|
import numpy as _np
|
||||||
|
|
||||||
|
from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence
|
||||||
from . import util as _util
|
from . import util as _util
|
||||||
from . import grid_filters as _grid_filters
|
from . import grid_filters as _grid_filters
|
||||||
|
|
||||||
|
|
||||||
def from_random(size: _np.ndarray, N_seeds: int, cells: _np.ndarray = None, rng_seed=None) -> _np.ndarray:
|
def from_random(size: _FloatSequence,
|
||||||
|
N_seeds: int,
|
||||||
|
cells: _IntSequence = None,
|
||||||
|
rng_seed=None) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Place seeds randomly in space.
|
Place seeds randomly in space.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the seeding domain.
|
Physical size of the seeding domain.
|
||||||
N_seeds : int
|
N_seeds : int
|
||||||
Number of seeds.
|
Number of seeds.
|
||||||
cells : numpy.ndarray of shape (3), optional.
|
cells : sequence of int, len (3), optional.
|
||||||
If given, ensures that each seed results in a grain when a standard Voronoi
|
If given, ensures that each seed results in a grain when a standard Voronoi
|
||||||
tessellation is performed using the given grid resolution (i.e. size/cells).
|
tessellation is performed using the given grid resolution (i.e. size/cells).
|
||||||
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
||||||
|
@ -28,29 +32,34 @@ def from_random(size: _np.ndarray, N_seeds: int, cells: _np.ndarray = None, rng_
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
coords : numpy.ndarray of shape (N_seeds,3)
|
coords : numpy.ndarray, shape (N_seeds,3)
|
||||||
Seed coordinates in 3D space.
|
Seed coordinates in 3D space.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
size_ = _np.array(size,float)
|
||||||
rng = _np.random.default_rng(rng_seed)
|
rng = _np.random.default_rng(rng_seed)
|
||||||
if cells is None:
|
if cells is None:
|
||||||
coords = rng.random((N_seeds,3)) * size
|
coords = rng.random((N_seeds,3)) * size_
|
||||||
else:
|
else:
|
||||||
grid_coords = _grid_filters.coordinates0_point(cells,size).reshape(-1,3,order='F')
|
grid_coords = _grid_filters.coordinates0_point(cells,size).reshape(-1,3,order='F')
|
||||||
coords = grid_coords[rng.choice(_np.prod(cells),N_seeds, replace=False)] \
|
coords = grid_coords[rng.choice(_np.prod(cells),N_seeds, replace=False)] \
|
||||||
+ _np.broadcast_to(size/cells,(N_seeds,3))*(rng.random((N_seeds,3))*.5-.25) # wobble without leaving cells
|
+ _np.broadcast_to(size_/_np.array(cells,int),(N_seeds,3))*(rng.random((N_seeds,3))*.5-.25) # wobble w/o leaving grid
|
||||||
|
|
||||||
return coords
|
return coords
|
||||||
|
|
||||||
|
|
||||||
def from_Poisson_disc(size: _np.ndarray, N_seeds: int, N_candidates: int, distance: float,
|
def from_Poisson_disc(size: _FloatSequence,
|
||||||
periodic: bool = True, rng_seed=None) -> _np.ndarray:
|
N_seeds: int,
|
||||||
|
N_candidates: int,
|
||||||
|
distance: float,
|
||||||
|
periodic: bool = True,
|
||||||
|
rng_seed=None) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Place seeds according to a Poisson disc distribution.
|
Place seeds according to a Poisson disc distribution.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
size : numpy.ndarray of shape (3)
|
size : sequence of float, len (3)
|
||||||
Physical size of the seeding domain.
|
Physical size of the seeding domain.
|
||||||
N_seeds : int
|
N_seeds : int
|
||||||
Number of seeds.
|
Number of seeds.
|
||||||
|
@ -58,7 +67,7 @@ def from_Poisson_disc(size: _np.ndarray, N_seeds: int, N_candidates: int, distan
|
||||||
Number of candidates to consider for finding best candidate.
|
Number of candidates to consider for finding best candidate.
|
||||||
distance : float
|
distance : float
|
||||||
Minimum acceptable distance to other seeds.
|
Minimum acceptable distance to other seeds.
|
||||||
periodic : boolean, optional
|
periodic : bool, optional
|
||||||
Calculate minimum distance for periodically repeated grid.
|
Calculate minimum distance for periodically repeated grid.
|
||||||
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
|
||||||
A seed to initialize the BitGenerator. Defaults to None.
|
A seed to initialize the BitGenerator. Defaults to None.
|
||||||
|
@ -66,27 +75,26 @@ def from_Poisson_disc(size: _np.ndarray, N_seeds: int, N_candidates: int, distan
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
coords : numpy.ndarray of shape (N_seeds,3)
|
coords : numpy.ndarray, shape (N_seeds,3)
|
||||||
Seed coordinates in 3D space.
|
Seed coordinates in 3D space.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
rng = _np.random.default_rng(rng_seed)
|
rng = _np.random.default_rng(rng_seed)
|
||||||
coords = _np.empty((N_seeds,3))
|
coords = _np.empty((N_seeds,3))
|
||||||
coords[0] = rng.random(3) * size
|
coords[0] = rng.random(3) * _np.array(size,float)
|
||||||
|
|
||||||
s = 1
|
s = 1
|
||||||
i = 0
|
i = 0
|
||||||
progress = _util._ProgressBar(N_seeds+1,'',50)
|
progress = _util.ProgressBar(N_seeds+1,'',50)
|
||||||
while s < N_seeds:
|
while s < N_seeds:
|
||||||
i += 1
|
i += 1
|
||||||
candidates = rng.random((N_candidates,3))*_np.broadcast_to(size,(N_candidates,3))
|
candidates = rng.random((N_candidates,3))*_np.broadcast_to(size,(N_candidates,3))
|
||||||
tree = _spatial.cKDTree(coords[:s],boxsize=size) if periodic else \
|
tree = _spatial.cKDTree(coords[:s],boxsize=size) if periodic else \
|
||||||
_spatial.cKDTree(coords[:s])
|
_spatial.cKDTree(coords[:s])
|
||||||
distances = tree.query(candidates)[0]
|
distances = tree.query(candidates)[0]
|
||||||
best = distances.argmax()
|
if distances.max() > distance: # require minimum separation
|
||||||
if distances[best] > distance: # require minimum separation
|
|
||||||
i = 0
|
i = 0
|
||||||
coords[s] = candidates[best] # maximum separation to existing point cloud
|
coords[s] = candidates[distances.argmax()] # maximum separation to existing point cloud
|
||||||
s += 1
|
s += 1
|
||||||
progress.update(s)
|
progress.update(s)
|
||||||
|
|
||||||
|
@ -96,8 +104,11 @@ def from_Poisson_disc(size: _np.ndarray, N_seeds: int, N_candidates: int, distan
|
||||||
return coords
|
return coords
|
||||||
|
|
||||||
|
|
||||||
def from_grid(grid, selection: Sequence[int] = None,
|
def from_grid(grid,
|
||||||
invert: bool = False, average: bool = False, periodic: bool = True) -> Tuple[_np.ndarray, _np.ndarray]:
|
selection: _IntSequence = None,
|
||||||
|
invert_selection: bool = False,
|
||||||
|
average: bool = False,
|
||||||
|
periodic: bool = True) -> _Tuple[_np.ndarray, _np.ndarray]:
|
||||||
"""
|
"""
|
||||||
Create seeds from grid description.
|
Create seeds from grid description.
|
||||||
|
|
||||||
|
@ -105,24 +116,24 @@ def from_grid(grid, selection: Sequence[int] = None,
|
||||||
----------
|
----------
|
||||||
grid : damask.Grid
|
grid : damask.Grid
|
||||||
Grid from which the material IDs are used as seeds.
|
Grid from which the material IDs are used as seeds.
|
||||||
selection : iterable of integers, optional
|
selection : sequence of int, optional
|
||||||
Material IDs to consider.
|
Material IDs to consider.
|
||||||
invert : boolean, false
|
invert_selection : bool, optional
|
||||||
Consider all material IDs except those in selection. Defaults to False.
|
Consider all material IDs except those in selection. Defaults to False.
|
||||||
average : boolean, optional
|
average : bool, optional
|
||||||
Seed corresponds to center of gravity of material ID cloud.
|
Seed corresponds to center of gravity of material ID cloud.
|
||||||
periodic : boolean, optional
|
periodic : bool, optional
|
||||||
Center of gravity accounts for periodic boundaries.
|
Center of gravity accounts for periodic boundaries.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
coords, materials : numpy.ndarray of shape (:,3), numpy.ndarray of shape (:)
|
coords, materials : numpy.ndarray, shape (:,3); numpy.ndarray, shape (:)
|
||||||
Seed coordinates in 3D space, material IDs.
|
Seed coordinates in 3D space, material IDs.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
material = grid.material.reshape((-1,1),order='F')
|
material = grid.material.reshape((-1,1),order='F')
|
||||||
mask = _np.full(grid.cells.prod(),True,dtype=bool) if selection is None else \
|
mask = _np.full(grid.cells.prod(),True,dtype=bool) if selection is None else \
|
||||||
_np.isin(material,selection,invert=invert).flatten()
|
_np.isin(material,selection,invert=invert_selection).flatten()
|
||||||
coords = _grid_filters.coordinates0_point(grid.cells,grid.size).reshape(-1,3,order='F')
|
coords = _grid_filters.coordinates0_point(grid.cells,grid.size).reshape(-1,3,order='F')
|
||||||
|
|
||||||
if not average:
|
if not average:
|
||||||
|
|
|
@ -45,7 +45,8 @@ def eigenvalues(T_sym: _np.ndarray) -> _np.ndarray:
|
||||||
return _np.linalg.eigvalsh(symmetric(T_sym))
|
return _np.linalg.eigvalsh(symmetric(T_sym))
|
||||||
|
|
||||||
|
|
||||||
def eigenvectors(T_sym: _np.ndarray, RHS: bool = False) -> _np.ndarray:
|
def eigenvectors(T_sym: _np.ndarray,
|
||||||
|
RHS: bool = False) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Eigenvectors of a symmetric tensor.
|
Eigenvectors of a symmetric tensor.
|
||||||
|
|
||||||
|
@ -63,14 +64,14 @@ def eigenvectors(T_sym: _np.ndarray, RHS: bool = False) -> _np.ndarray:
|
||||||
associated eigenvalues.
|
associated eigenvalues.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
(u,v) = _np.linalg.eigh(symmetric(T_sym))
|
_,v = _np.linalg.eigh(symmetric(T_sym))
|
||||||
|
|
||||||
if RHS:
|
if RHS: v[_np.linalg.det(v) < 0.0,:,2] *= -1.0
|
||||||
v[_np.linalg.det(v) < 0.0,:,2] *= -1.0
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def spherical(T: _np.ndarray, tensor: bool = True) -> _np.ndarray:
|
def spherical(T: _np.ndarray,
|
||||||
|
tensor: bool = True) -> _np.ndarray:
|
||||||
"""
|
"""
|
||||||
Calculate spherical part of a tensor.
|
Calculate spherical part of a tensor.
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,16 @@ import subprocess
|
||||||
import shlex
|
import shlex
|
||||||
import re
|
import re
|
||||||
import fractions
|
import fractions
|
||||||
|
from collections import abc
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, SupportsIndex, Sequence
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import h5py
|
import h5py
|
||||||
|
|
||||||
from . import version
|
from . import version
|
||||||
|
from ._typehints import IntSequence, FloatSequence
|
||||||
|
|
||||||
# limit visibility
|
# limit visibility
|
||||||
__all__=[
|
__all__=[
|
||||||
|
@ -50,16 +54,17 @@ _colors = {
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Functions
|
# Functions
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
def srepr(arg,glue = '\n'):
|
def srepr(msg,
|
||||||
|
glue: str = '\n') -> str:
|
||||||
r"""
|
r"""
|
||||||
Join items with glue string.
|
Join items with glue string.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
arg : iterable
|
msg : object with __repr__ or sequence of objects with __repr__
|
||||||
Items to join.
|
Items to join.
|
||||||
glue : str, optional
|
glue : str, optional
|
||||||
Glue used for joining operation. Defaults to \n.
|
Glue used for joining operation. Defaults to '\n'.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
@ -67,21 +72,21 @@ def srepr(arg,glue = '\n'):
|
||||||
String representation of the joined items.
|
String representation of the joined items.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if (not hasattr(arg, 'strip') and
|
if (not hasattr(msg, 'strip') and
|
||||||
(hasattr(arg, '__getitem__') or
|
(hasattr(msg, '__getitem__') or
|
||||||
hasattr(arg, '__iter__'))):
|
hasattr(msg, '__iter__'))):
|
||||||
return glue.join(str(x) for x in arg)
|
return glue.join(str(x) for x in msg)
|
||||||
else:
|
else:
|
||||||
return arg if isinstance(arg,str) else repr(arg)
|
return msg if isinstance(msg,str) else repr(msg)
|
||||||
|
|
||||||
|
|
||||||
def emph(what):
|
def emph(msg) -> str:
|
||||||
"""
|
"""
|
||||||
Format with emphasis.
|
Format with emphasis.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
what : object with __repr__ or iterable of objects with __repr__.
|
msg : object with __repr__ or sequence of objects with __repr__
|
||||||
Message to format.
|
Message to format.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -90,15 +95,15 @@ def emph(what):
|
||||||
Formatted string representation of the joined items.
|
Formatted string representation of the joined items.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return _colors['bold']+srepr(what)+_colors['end_color']
|
return _colors['bold']+srepr(msg)+_colors['end_color']
|
||||||
|
|
||||||
def deemph(what):
|
def deemph(msg) -> str:
|
||||||
"""
|
"""
|
||||||
Format with deemphasis.
|
Format with deemphasis.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
what : object with __repr__ or iterable of objects with __repr__.
|
msg : object with __repr__ or sequence of objects with __repr__
|
||||||
Message to format.
|
Message to format.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -107,15 +112,15 @@ def deemph(what):
|
||||||
Formatted string representation of the joined items.
|
Formatted string representation of the joined items.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return _colors['dim']+srepr(what)+_colors['end_color']
|
return _colors['dim']+srepr(msg)+_colors['end_color']
|
||||||
|
|
||||||
def warn(what):
|
def warn(msg) -> str:
|
||||||
"""
|
"""
|
||||||
Format for warning.
|
Format for warning.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
what : object with __repr__ or iterable of objects with __repr__.
|
msg : object with __repr__ or sequence of objects with __repr__
|
||||||
Message to format.
|
Message to format.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -124,15 +129,15 @@ def warn(what):
|
||||||
Formatted string representation of the joined items.
|
Formatted string representation of the joined items.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return _colors['warning']+emph(what)+_colors['end_color']
|
return _colors['warning']+emph(msg)+_colors['end_color']
|
||||||
|
|
||||||
def strikeout(what):
|
def strikeout(msg) -> str:
|
||||||
"""
|
"""
|
||||||
Format as strikeout.
|
Format as strikeout.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
what : object with __repr__ or iterable of objects with __repr__.
|
msg : object with __repr__ or iterable of objects with __repr__
|
||||||
Message to format.
|
Message to format.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -141,10 +146,13 @@ def strikeout(what):
|
||||||
Formatted string representation of the joined items.
|
Formatted string representation of the joined items.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return _colors['crossout']+srepr(what)+_colors['end_color']
|
return _colors['crossout']+srepr(msg)+_colors['end_color']
|
||||||
|
|
||||||
|
|
||||||
def run(cmd,wd='./',env=None,timeout=None):
|
def run(cmd: str,
|
||||||
|
wd: str = './',
|
||||||
|
env: Dict[str, str] = None,
|
||||||
|
timeout: int = None) -> Tuple[str, str]:
|
||||||
"""
|
"""
|
||||||
Run a command.
|
Run a command.
|
||||||
|
|
||||||
|
@ -153,7 +161,7 @@ def run(cmd,wd='./',env=None,timeout=None):
|
||||||
cmd : str
|
cmd : str
|
||||||
Command to be executed.
|
Command to be executed.
|
||||||
wd : str, optional
|
wd : str, optional
|
||||||
Working directory of process. Defaults to ./ .
|
Working directory of process. Defaults to './'.
|
||||||
env : dict, optional
|
env : dict, optional
|
||||||
Environment for execution.
|
Environment for execution.
|
||||||
timeout : integer, optional
|
timeout : integer, optional
|
||||||
|
@ -185,7 +193,7 @@ def run(cmd,wd='./',env=None,timeout=None):
|
||||||
execute = run
|
execute = run
|
||||||
|
|
||||||
|
|
||||||
def natural_sort(key):
|
def natural_sort(key: str) -> List[Union[int, str]]:
|
||||||
"""
|
"""
|
||||||
Natural sort.
|
Natural sort.
|
||||||
|
|
||||||
|
@ -200,7 +208,10 @@ def natural_sort(key):
|
||||||
return [ convert(c) for c in re.split('([0-9]+)', key) ]
|
return [ convert(c) for c in re.split('([0-9]+)', key) ]
|
||||||
|
|
||||||
|
|
||||||
def show_progress(iterable,N_iter=None,prefix='',bar_length=50):
|
def show_progress(iterable: Iterable,
|
||||||
|
N_iter: int = None,
|
||||||
|
prefix: str = '',
|
||||||
|
bar_length: int = 50) -> Any:
|
||||||
"""
|
"""
|
||||||
Decorate a loop with a progress bar.
|
Decorate a loop with a progress bar.
|
||||||
|
|
||||||
|
@ -208,39 +219,49 @@ def show_progress(iterable,N_iter=None,prefix='',bar_length=50):
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
iterable : iterable or function with yield statement
|
iterable : iterable
|
||||||
Iterable (or function with yield statement) to be decorated.
|
Iterable to be decorated.
|
||||||
N_iter : int, optional
|
N_iter : int, optional
|
||||||
Total number of iterations. Required unless obtainable as len(iterable).
|
Total number of iterations. Required if iterable is not a sequence.
|
||||||
prefix : str, optional
|
prefix : str, optional
|
||||||
Prefix string.
|
Prefix string.
|
||||||
bar_length : int, optional
|
bar_length : int, optional
|
||||||
Length of progress bar in characters. Defaults to 50.
|
Length of progress bar in characters. Defaults to 50.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if N_iter in [0,1] or (hasattr(iterable,'__len__') and len(iterable) <= 1):
|
if isinstance(iterable,abc.Sequence):
|
||||||
|
if N_iter is None:
|
||||||
|
N = len(iterable)
|
||||||
|
else:
|
||||||
|
raise ValueError('N_iter given for sequence')
|
||||||
|
else:
|
||||||
|
if N_iter is None:
|
||||||
|
raise ValueError('N_iter not given')
|
||||||
|
|
||||||
|
N = N_iter
|
||||||
|
|
||||||
|
if N <= 1:
|
||||||
for item in iterable:
|
for item in iterable:
|
||||||
yield item
|
yield item
|
||||||
else:
|
else:
|
||||||
status = _ProgressBar(N_iter if N_iter is not None else len(iterable),prefix,bar_length)
|
status = ProgressBar(N,prefix,bar_length)
|
||||||
|
|
||||||
for i,item in enumerate(iterable):
|
for i,item in enumerate(iterable):
|
||||||
yield item
|
yield item
|
||||||
status.update(i)
|
status.update(i)
|
||||||
|
|
||||||
|
|
||||||
def scale_to_coprime(v):
|
def scale_to_coprime(v: FloatSequence) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Scale vector to co-prime (relatively prime) integers.
|
Scale vector to co-prime (relatively prime) integers.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
v : numpy.ndarray of shape (:)
|
v : sequence of float, len (:)
|
||||||
Vector to scale.
|
Vector to scale.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
m : numpy.ndarray of shape (:)
|
m : numpy.ndarray, shape (:)
|
||||||
Vector scaled to co-prime numbers.
|
Vector scaled to co-prime numbers.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -257,17 +278,21 @@ def scale_to_coprime(v):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return a * b // np.gcd(a, b)
|
return a * b // np.gcd(a, b)
|
||||||
|
|
||||||
m = (np.array(v) * reduce(lcm, map(lambda x: int(get_square_denominator(x)),v)) ** 0.5).astype(int)
|
v_ = np.array(v)
|
||||||
|
m = (v_ * reduce(lcm, map(lambda x: int(get_square_denominator(x)),v_))**0.5).astype(int)
|
||||||
m = m//reduce(np.gcd,m)
|
m = m//reduce(np.gcd,m)
|
||||||
|
|
||||||
with np.errstate(invalid='ignore'):
|
with np.errstate(invalid='ignore'):
|
||||||
if not np.allclose(np.ma.masked_invalid(v/m),v[np.argmax(abs(v))]/m[np.argmax(abs(v))]):
|
if not np.allclose(np.ma.masked_invalid(v_/m),v_[np.argmax(abs(v_))]/m[np.argmax(abs(v_))]):
|
||||||
raise ValueError(f'Invalid result {m} for input {v}. Insufficient precision?')
|
raise ValueError(f'Invalid result {m} for input {v_}. Insufficient precision?')
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|
||||||
def project_equal_angle(vector,direction='z',normalize=True,keepdims=False):
|
def project_equal_angle(vector: np.ndarray,
|
||||||
|
direction: Literal['x', 'y', 'z'] = 'z',
|
||||||
|
normalize: bool = True,
|
||||||
|
keepdims: bool = False) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Apply equal-angle projection to vector.
|
Apply equal-angle projection to vector.
|
||||||
|
|
||||||
|
@ -275,22 +300,25 @@ def project_equal_angle(vector,direction='z',normalize=True,keepdims=False):
|
||||||
----------
|
----------
|
||||||
vector : numpy.ndarray, shape (...,3)
|
vector : numpy.ndarray, shape (...,3)
|
||||||
Vector coordinates to be projected.
|
Vector coordinates to be projected.
|
||||||
direction : str
|
direction : {'x', 'y', 'z'}
|
||||||
Projection direction 'x', 'y', or 'z'.
|
Projection direction. Defaults to 'z'.
|
||||||
Defaults to 'z'.
|
|
||||||
normalize : bool
|
normalize : bool
|
||||||
Ensure unit length of input vector. Defaults to True.
|
Ensure unit length of input vector. Defaults to True.
|
||||||
keepdims : bool
|
keepdims : bool
|
||||||
Maintain three-dimensional output coordinates. Defaults to False.
|
Maintain three-dimensional output coordinates.
|
||||||
Two-dimensional output uses right-handed frame spanned by
|
Defaults to False.
|
||||||
the next and next-next axis relative to the projection direction,
|
|
||||||
e.g. x-y when projecting along z and z-x when projecting along y.
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
coordinates : numpy.ndarray, shape (...,2 | 3)
|
coordinates : numpy.ndarray, shape (...,2 | 3)
|
||||||
Projected coordinates.
|
Projected coordinates.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
Two-dimensional output uses right-handed frame spanned by
|
||||||
|
the next and next-next axis relative to the projection direction,
|
||||||
|
e.g. x-y when projecting along z and z-x when projecting along y.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
>>> import damask
|
>>> import damask
|
||||||
|
@ -309,7 +337,10 @@ def project_equal_angle(vector,direction='z',normalize=True,keepdims=False):
|
||||||
return np.roll(np.block([v[...,:2]/(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]),
|
return np.roll(np.block([v[...,:2]/(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]),
|
||||||
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
|
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
|
||||||
|
|
||||||
def project_equal_area(vector,direction='z',normalize=True,keepdims=False):
|
def project_equal_area(vector: np.ndarray,
|
||||||
|
direction: Literal['x', 'y', 'z'] = 'z',
|
||||||
|
normalize: bool = True,
|
||||||
|
keepdims: bool = False) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Apply equal-area projection to vector.
|
Apply equal-area projection to vector.
|
||||||
|
|
||||||
|
@ -317,22 +348,26 @@ def project_equal_area(vector,direction='z',normalize=True,keepdims=False):
|
||||||
----------
|
----------
|
||||||
vector : numpy.ndarray, shape (...,3)
|
vector : numpy.ndarray, shape (...,3)
|
||||||
Vector coordinates to be projected.
|
Vector coordinates to be projected.
|
||||||
direction : str
|
direction : {'x', 'y', 'z'}
|
||||||
Projection direction 'x', 'y', or 'z'.
|
Projection direction. Defaults to 'z'.
|
||||||
Defaults to 'z'.
|
|
||||||
normalize : bool
|
normalize : bool
|
||||||
Ensure unit length of input vector. Defaults to True.
|
Ensure unit length of input vector. Defaults to True.
|
||||||
keepdims : bool
|
keepdims : bool
|
||||||
Maintain three-dimensional output coordinates. Defaults to False.
|
Maintain three-dimensional output coordinates.
|
||||||
Two-dimensional output uses right-handed frame spanned by
|
Defaults to False.
|
||||||
the next and next-next axis relative to the projection direction,
|
|
||||||
e.g. x-y when projecting along z and z-x when projecting along y.
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
coordinates : numpy.ndarray, shape (...,2 | 3)
|
coordinates : numpy.ndarray, shape (...,2 | 3)
|
||||||
Projected coordinates.
|
Projected coordinates.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
Two-dimensional output uses right-handed frame spanned by
|
||||||
|
the next and next-next axis relative to the projection direction,
|
||||||
|
e.g. x-y when projecting along z and z-x when projecting along y.
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
>>> import damask
|
>>> import damask
|
||||||
|
@ -351,15 +386,17 @@ def project_equal_area(vector,direction='z',normalize=True,keepdims=False):
|
||||||
return np.roll(np.block([v[...,:2]/np.sqrt(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]),
|
return np.roll(np.block([v[...,:2]/np.sqrt(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]),
|
||||||
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
|
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
|
||||||
|
|
||||||
|
def execution_stamp(class_name: str,
|
||||||
def execution_stamp(class_name,function_name=None):
|
function_name: str = None) -> str:
|
||||||
"""Timestamp the execution of a (function within a) class."""
|
"""Timestamp the execution of a (function within a) class."""
|
||||||
now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z')
|
now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z')
|
||||||
_function_name = '' if function_name is None else f'.{function_name}'
|
_function_name = '' if function_name is None else f'.{function_name}'
|
||||||
return f'damask.{class_name}{_function_name} v{version} ({now})'
|
return f'damask.{class_name}{_function_name} v{version} ({now})'
|
||||||
|
|
||||||
|
|
||||||
def hybrid_IA(dist,N,rng_seed=None):
|
def hybrid_IA(dist: np.ndarray,
|
||||||
|
N: int,
|
||||||
|
rng_seed: Union[int, IntSequence] = None) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Hybrid integer approximation.
|
Hybrid integer approximation.
|
||||||
|
|
||||||
|
@ -387,7 +424,10 @@ def hybrid_IA(dist,N,rng_seed=None):
|
||||||
return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]]
|
return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]]
|
||||||
|
|
||||||
|
|
||||||
def shapeshifter(fro,to,mode='left',keep_ones=False):
|
def shapeshifter(fro: Tuple[int, ...],
|
||||||
|
to: Tuple[int, ...],
|
||||||
|
mode: Literal['left','right'] = 'left',
|
||||||
|
keep_ones: bool = False) -> Sequence[SupportsIndex]:
|
||||||
"""
|
"""
|
||||||
Return dimensions that reshape 'fro' to become broadcastable to 'to'.
|
Return dimensions that reshape 'fro' to become broadcastable to 'to'.
|
||||||
|
|
||||||
|
@ -398,9 +438,9 @@ def shapeshifter(fro,to,mode='left',keep_ones=False):
|
||||||
to : tuple
|
to : tuple
|
||||||
Target shape of array after broadcasting.
|
Target shape of array after broadcasting.
|
||||||
len(to) cannot be less than len(fro).
|
len(to) cannot be less than len(fro).
|
||||||
mode : str, optional
|
mode : {'left', 'right'}, optional
|
||||||
Indicates whether new axes are preferably added to
|
Indicates whether new axes are preferably added to
|
||||||
either 'left' or 'right' of the original shape.
|
either left or right of the original shape.
|
||||||
Defaults to 'left'.
|
Defaults to 'left'.
|
||||||
keep_ones : bool, optional
|
keep_ones : bool, optional
|
||||||
Treat '1' in fro as literal value instead of dimensional placeholder.
|
Treat '1' in fro as literal value instead of dimensional placeholder.
|
||||||
|
@ -423,7 +463,7 @@ def shapeshifter(fro,to,mode='left',keep_ones=False):
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not len(fro) and not len(to): return ()
|
if len(fro) == 0 and len(to) == 0: return ()
|
||||||
|
|
||||||
beg = dict(left ='(^.*\\b)',
|
beg = dict(left ='(^.*\\b)',
|
||||||
right='(^.*?\\b)')
|
right='(^.*?\\b)')
|
||||||
|
@ -431,24 +471,26 @@ def shapeshifter(fro,to,mode='left',keep_ones=False):
|
||||||
right='(.*?\\b)')
|
right='(.*?\\b)')
|
||||||
end = dict(left ='(.*?$)',
|
end = dict(left ='(.*?$)',
|
||||||
right='(.*$)')
|
right='(.*$)')
|
||||||
fro = (1,) if not len(fro) else fro
|
fro = (1,) if len(fro) == 0 else fro
|
||||||
to = (1,) if not len(to) else to
|
to = (1,) if len(to) == 0 else to
|
||||||
try:
|
try:
|
||||||
grp = re.match(beg[mode]
|
match = re.match(beg[mode]
|
||||||
+f',{sep[mode]}'.join(map(lambda x: f'{x}'
|
+f',{sep[mode]}'.join(map(lambda x: f'{x}'
|
||||||
if x>1 or (keep_ones and len(fro)>1) else
|
if x>1 or (keep_ones and len(fro)>1) else
|
||||||
'\\d+',fro))
|
'\\d+',fro))
|
||||||
+f',{end[mode]}',
|
+f',{end[mode]}',','.join(map(str,to))+',')
|
||||||
','.join(map(str,to))+',').groups()
|
assert match
|
||||||
except AttributeError:
|
grp = match.groups()
|
||||||
|
except AssertionError:
|
||||||
raise ValueError(f'Shapes can not be shifted {fro} --> {to}')
|
raise ValueError(f'Shapes can not be shifted {fro} --> {to}')
|
||||||
fill = ()
|
fill: Any = ()
|
||||||
for g,d in zip(grp,fro+(None,)):
|
for g,d in zip(grp,fro+(None,)):
|
||||||
fill += (1,)*g.count(',')+(d,)
|
fill += (1,)*g.count(',')+(d,)
|
||||||
return fill[:-1]
|
return fill[:-1]
|
||||||
|
|
||||||
|
|
||||||
def shapeblender(a,b):
|
def shapeblender(a: Tuple[int, ...],
|
||||||
|
b: Tuple[int, ...]) -> Sequence[SupportsIndex]:
|
||||||
"""
|
"""
|
||||||
Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'.
|
Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'.
|
||||||
|
|
||||||
|
@ -476,7 +518,7 @@ def shapeblender(a,b):
|
||||||
return a + b[i:]
|
return a + b[i:]
|
||||||
|
|
||||||
|
|
||||||
def extend_docstring(extra_docstring):
|
def extend_docstring(extra_docstring: str) -> Callable:
|
||||||
"""
|
"""
|
||||||
Decorator: Append to function's docstring.
|
Decorator: Append to function's docstring.
|
||||||
|
|
||||||
|
@ -492,7 +534,8 @@ def extend_docstring(extra_docstring):
|
||||||
return _decorator
|
return _decorator
|
||||||
|
|
||||||
|
|
||||||
def extended_docstring(f,extra_docstring):
|
def extended_docstring(f: Callable,
|
||||||
|
extra_docstring: str) -> Callable:
|
||||||
"""
|
"""
|
||||||
Decorator: Combine another function's docstring with a given docstring.
|
Decorator: Combine another function's docstring with a given docstring.
|
||||||
|
|
||||||
|
@ -510,7 +553,7 @@ def extended_docstring(f,extra_docstring):
|
||||||
return _decorator
|
return _decorator
|
||||||
|
|
||||||
|
|
||||||
def DREAM3D_base_group(fname):
|
def DREAM3D_base_group(fname: Union[str, Path]) -> str:
|
||||||
"""
|
"""
|
||||||
Determine the base group of a DREAM.3D file.
|
Determine the base group of a DREAM.3D file.
|
||||||
|
|
||||||
|
@ -536,7 +579,7 @@ def DREAM3D_base_group(fname):
|
||||||
|
|
||||||
return base_group
|
return base_group
|
||||||
|
|
||||||
def DREAM3D_cell_data_group(fname):
|
def DREAM3D_cell_data_group(fname: Union[str, Path]) -> str:
|
||||||
"""
|
"""
|
||||||
Determine the cell data group of a DREAM.3D file.
|
Determine the cell data group of a DREAM.3D file.
|
||||||
|
|
||||||
|
@ -568,18 +611,20 @@ def DREAM3D_cell_data_group(fname):
|
||||||
return cell_data_group
|
return cell_data_group
|
||||||
|
|
||||||
|
|
||||||
def Bravais_to_Miller(*,uvtw=None,hkil=None):
|
def Bravais_to_Miller(*,
|
||||||
|
uvtw: np.ndarray = None,
|
||||||
|
hkil: np.ndarray = None) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Transform 4 Miller–Bravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl).
|
Transform 4 Miller–Bravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl).
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
uvtw|hkil : numpy.ndarray of shape (...,4)
|
uvtw|hkil : numpy.ndarray, shape (...,4)
|
||||||
Miller–Bravais indices of crystallographic direction [uvtw] or plane normal (hkil).
|
Miller–Bravais indices of crystallographic direction [uvtw] or plane normal (hkil).
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
uvw|hkl : numpy.ndarray of shape (...,3)
|
uvw|hkl : numpy.ndarray, shape (...,3)
|
||||||
Miller indices of [uvw] direction or (hkl) plane normal.
|
Miller indices of [uvw] direction or (hkl) plane normal.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -595,18 +640,20 @@ def Bravais_to_Miller(*,uvtw=None,hkil=None):
|
||||||
return np.einsum('il,...l',basis,axis)
|
return np.einsum('il,...l',basis,axis)
|
||||||
|
|
||||||
|
|
||||||
def Miller_to_Bravais(*,uvw=None,hkl=None):
|
def Miller_to_Bravais(*,
|
||||||
|
uvw: np.ndarray = None,
|
||||||
|
hkl: np.ndarray = None) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Transform 3 Miller indices to 4 Miller–Bravais indices of crystal direction [uvtw] or plane normal (hkil).
|
Transform 3 Miller indices to 4 Miller–Bravais indices of crystal direction [uvtw] or plane normal (hkil).
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
uvw|hkl : numpy.ndarray of shape (...,3)
|
uvw|hkl : numpy.ndarray, shape (...,3)
|
||||||
Miller indices of crystallographic direction [uvw] or plane normal (hkl).
|
Miller indices of crystallographic direction [uvw] or plane normal (hkl).
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
uvtw|hkil : numpy.ndarray of shape (...,4)
|
uvtw|hkil : numpy.ndarray, shape (...,4)
|
||||||
Miller–Bravais indices of [uvtw] direction or (hkil) plane normal.
|
Miller–Bravais indices of [uvtw] direction or (hkil) plane normal.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -624,7 +671,7 @@ def Miller_to_Bravais(*,uvw=None,hkl=None):
|
||||||
return np.einsum('il,...l',basis,axis)
|
return np.einsum('il,...l',basis,axis)
|
||||||
|
|
||||||
|
|
||||||
def dict_prune(d):
|
def dict_prune(d: Dict) -> Dict:
|
||||||
"""
|
"""
|
||||||
Recursively remove empty dictionaries.
|
Recursively remove empty dictionaries.
|
||||||
|
|
||||||
|
@ -650,7 +697,7 @@ def dict_prune(d):
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
def dict_flatten(d):
|
def dict_flatten(d: Dict) -> Dict:
|
||||||
"""
|
"""
|
||||||
Recursively remove keys of single-entry dictionaries.
|
Recursively remove keys of single-entry dictionaries.
|
||||||
|
|
||||||
|
@ -678,14 +725,17 @@ def dict_flatten(d):
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Classes
|
# Classes
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
class _ProgressBar:
|
class ProgressBar:
|
||||||
"""
|
"""
|
||||||
Report progress of an interation as a status bar.
|
Report progress of an interation as a status bar.
|
||||||
|
|
||||||
Works for 0-based loops, ETA is estimated by linear extrapolation.
|
Works for 0-based loops, ETA is estimated by linear extrapolation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,total,prefix,bar_length):
|
def __init__(self,
|
||||||
|
total: int,
|
||||||
|
prefix: str,
|
||||||
|
bar_length: int):
|
||||||
"""
|
"""
|
||||||
Set current time as basis for ETA estimation.
|
Set current time as basis for ETA estimation.
|
||||||
|
|
||||||
|
@ -708,12 +758,12 @@ class _ProgressBar:
|
||||||
sys.stderr.write(f"{self.prefix} {'░'*self.bar_length} 0% ETA n/a")
|
sys.stderr.write(f"{self.prefix} {'░'*self.bar_length} 0% ETA n/a")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
|
||||||
def update(self,iteration):
|
def update(self,
|
||||||
|
iteration: int) -> None:
|
||||||
|
|
||||||
fraction = (iteration+1) / self.total
|
fraction = (iteration+1) / self.total
|
||||||
filled_length = int(self.bar_length * fraction)
|
|
||||||
|
|
||||||
if filled_length > int(self.bar_length * self.fraction_last) or \
|
if filled_length := int(self.bar_length * fraction) > int(self.bar_length * self.fraction_last) or \
|
||||||
datetime.datetime.now() - self.time_last_update > datetime.timedelta(seconds=10):
|
datetime.datetime.now() - self.time_last_update > datetime.timedelta(seconds=10):
|
||||||
self.time_last_update = datetime.datetime.now()
|
self.time_last_update = datetime.datetime.now()
|
||||||
bar = '█' * filled_length + '░' * (self.bar_length - filled_length)
|
bar = '█' * filled_length + '░' * (self.bar_length - filled_length)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
[mypy]
|
||||||
|
warn_redundant_casts = True
|
||||||
[mypy-scipy.*]
|
[mypy-scipy.*]
|
||||||
ignore_missing_imports = True
|
ignore_missing_imports = True
|
||||||
[mypy-h5py.*]
|
[mypy-h5py.*]
|
||||||
|
|
|
@ -16,7 +16,7 @@ setuptools.setup(
|
||||||
url='https://damask.mpie.de',
|
url='https://damask.mpie.de',
|
||||||
packages=setuptools.find_packages(),
|
packages=setuptools.find_packages(),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
python_requires = '>=3.7',
|
python_requires = '>=3.8',
|
||||||
install_requires = [
|
install_requires = [
|
||||||
'pandas>=0.24', # requires numpy
|
'pandas>=0.24', # requires numpy
|
||||||
'numpy>=1.17', # needed for default_rng
|
'numpy>=1.17', # needed for default_rng
|
||||||
|
@ -30,7 +30,7 @@ setuptools.setup(
|
||||||
'Intended Audience :: Science/Research',
|
'Intended Audience :: Science/Research',
|
||||||
'Topic :: Scientific/Engineering',
|
'Topic :: Scientific/Engineering',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
|
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -81,6 +81,7 @@ class TestColormap:
|
||||||
assert Colormap.from_predefined('strain') == Colormap.from_predefined('strain')
|
assert Colormap.from_predefined('strain') == Colormap.from_predefined('strain')
|
||||||
assert Colormap.from_predefined('strain') != Colormap.from_predefined('stress')
|
assert Colormap.from_predefined('strain') != Colormap.from_predefined('stress')
|
||||||
assert Colormap.from_predefined('strain',N=128) != Colormap.from_predefined('strain',N=64)
|
assert Colormap.from_predefined('strain',N=128) != Colormap.from_predefined('strain',N=64)
|
||||||
|
assert not Colormap.from_predefined('strain',N=128) == 1
|
||||||
|
|
||||||
@pytest.mark.parametrize('low,high',[((0,0,0),(1,1,1)),
|
@pytest.mark.parametrize('low,high',[((0,0,0),(1,1,1)),
|
||||||
([0,0,0],[1,1,1])])
|
([0,0,0],[1,1,1])])
|
||||||
|
@ -139,6 +140,11 @@ class TestColormap:
|
||||||
c += c
|
c += c
|
||||||
assert (np.allclose(c.colors[:len(c.colors)//2],c.colors[len(c.colors)//2:]))
|
assert (np.allclose(c.colors[:len(c.colors)//2],c.colors[len(c.colors)//2:]))
|
||||||
|
|
||||||
|
def test_mul(self):
|
||||||
|
c = o = Colormap.from_predefined('jet')
|
||||||
|
o *= 2
|
||||||
|
assert c+c == o
|
||||||
|
|
||||||
@pytest.mark.parametrize('N,cmap,at,result',[
|
@pytest.mark.parametrize('N,cmap,at,result',[
|
||||||
(8,'gray',0.5,[0.5,0.5,0.5]),
|
(8,'gray',0.5,[0.5,0.5,0.5]),
|
||||||
(17,'gray',0.5,[0.5,0.5,0.5]),
|
(17,'gray',0.5,[0.5,0.5,0.5]),
|
||||||
|
|
|
@ -40,6 +40,9 @@ class TestCrystal:
|
||||||
alpha=alpha,beta=beta,gamma=gamma)
|
alpha=alpha,beta=beta,gamma=gamma)
|
||||||
assert np.allclose(np.eye(3),np.einsum('ik,jk',c.basis_real,c.basis_reciprocal))
|
assert np.allclose(np.eye(3),np.einsum('ik,jk',c.basis_real,c.basis_reciprocal))
|
||||||
|
|
||||||
|
def test_basis_invalid(self):
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
Crystal(family='cubic').basis_real
|
||||||
|
|
||||||
@pytest.mark.parametrize('keyFrame,keyLattice',[('uvw','direction'),('hkl','plane'),])
|
@pytest.mark.parametrize('keyFrame,keyLattice',[('uvw','direction'),('hkl','plane'),])
|
||||||
@pytest.mark.parametrize('vector',np.array([
|
@pytest.mark.parametrize('vector',np.array([
|
||||||
|
|
|
@ -44,6 +44,7 @@ class TestGrid:
|
||||||
|
|
||||||
def test_equal(self,default):
|
def test_equal(self,default):
|
||||||
assert default == default
|
assert default == default
|
||||||
|
assert not default == 42
|
||||||
|
|
||||||
def test_repr(self,default):
|
def test_repr(self,default):
|
||||||
print(default)
|
print(default)
|
||||||
|
@ -237,12 +238,27 @@ class TestGrid:
|
||||||
modified)
|
modified)
|
||||||
|
|
||||||
|
|
||||||
def test_canvas(self,default):
|
def test_canvas_extend(self,default):
|
||||||
cells = default.cells
|
cells = default.cells
|
||||||
grid_add = np.random.randint(0,30,(3))
|
cells_add = np.random.randint(0,30,(3))
|
||||||
modified = default.canvas(cells + grid_add)
|
modified = default.canvas(cells + cells_add)
|
||||||
assert np.all(modified.material[:cells[0],:cells[1],:cells[2]] == default.material)
|
assert np.all(modified.material[:cells[0],:cells[1],:cells[2]] == default.material)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('sign',[+1,-1])
|
||||||
|
@pytest.mark.parametrize('extra_offset',[0,-1])
|
||||||
|
def test_canvas_move_out(self,sign,extra_offset):
|
||||||
|
g = Grid(np.zeros(np.random.randint(3,30,(3)),int),np.ones(3))
|
||||||
|
o = sign*np.ones(3)*g.cells.min() +extra_offset*sign
|
||||||
|
if extra_offset == 0:
|
||||||
|
assert np.all(g.canvas(offset=o).material == 1)
|
||||||
|
else:
|
||||||
|
assert np.all(np.unique(g.canvas(offset=o).material) == (0,1))
|
||||||
|
|
||||||
|
def test_canvas_cells(self,default):
|
||||||
|
g = Grid(np.zeros(np.random.randint(3,30,(3)),int),np.ones(3))
|
||||||
|
cells = np.random.randint(1,30,(3))
|
||||||
|
offset = np.random.randint(-30,30,(3))
|
||||||
|
assert np.all(g.canvas(cells,offset).cells == cells)
|
||||||
|
|
||||||
@pytest.mark.parametrize('center1,center2',[(np.random.random(3)*.5,np.random.random()*8),
|
@pytest.mark.parametrize('center1,center2',[(np.random.random(3)*.5,np.random.random()*8),
|
||||||
(np.random.randint(4,8,(3)),np.random.randint(9,12,(3)))])
|
(np.random.randint(4,8,(3)),np.random.randint(9,12,(3)))])
|
||||||
|
|
|
@ -364,6 +364,11 @@ class TestOrientation:
|
||||||
table.save(reference)
|
table.save(reference)
|
||||||
assert np.allclose(P,Table.load(reference).get('Schmid'))
|
assert np.allclose(P,Table.load(reference).get('Schmid'))
|
||||||
|
|
||||||
|
def test_Schmid_invalid(self):
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
Orientation(lattice='fcc').Schmid()
|
||||||
|
|
||||||
|
|
||||||
### vectorization tests ###
|
### vectorization tests ###
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',['hP','cI','cF']) # tI not included yet
|
@pytest.mark.parametrize('lattice',['hP','cI','cF']) # tI not included yet
|
||||||
|
@ -505,3 +510,7 @@ class TestOrientation:
|
||||||
for loc in np.random.randint(0,blend,(10,len(blend))):
|
for loc in np.random.randint(0,blend,(10,len(blend))):
|
||||||
assert np.allclose(o[tuple(loc[:len(o.shape)])].to_pole(uvw=v[tuple(loc[-len(v.shape[:-1]):])]),
|
assert np.allclose(o[tuple(loc[:len(o.shape)])].to_pole(uvw=v[tuple(loc[-len(v.shape[:-1]):])]),
|
||||||
o.to_pole(uvw=v)[tuple(loc)])
|
o.to_pole(uvw=v)[tuple(loc)])
|
||||||
|
|
||||||
|
def test_mul_invalid(self):
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
Orientation.from_random(lattice='cF')*np.ones(3)
|
||||||
|
|
|
@ -102,6 +102,9 @@ class TestResult:
|
||||||
with pytest.raises(AttributeError):
|
with pytest.raises(AttributeError):
|
||||||
default.view('invalid',True)
|
default.view('invalid',True)
|
||||||
|
|
||||||
|
def test_add_invalid(self,default):
|
||||||
|
default.add_absolute('xxxx')
|
||||||
|
|
||||||
def test_add_absolute(self,default):
|
def test_add_absolute(self,default):
|
||||||
default.add_absolute('F_e')
|
default.add_absolute('F_e')
|
||||||
in_memory = np.abs(default.place('F_e'))
|
in_memory = np.abs(default.place('F_e'))
|
||||||
|
|
|
@ -792,6 +792,11 @@ class TestRotation:
|
||||||
R = Rotation.from_random(shape,rng_seed=1)
|
R = Rotation.from_random(shape,rng_seed=1)
|
||||||
assert R == R if shape is None else (R == R).all()
|
assert R == R if shape is None else (R == R).all()
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
||||||
|
def test_allclose(self,shape):
|
||||||
|
R = Rotation.from_random(shape,rng_seed=1)
|
||||||
|
assert R.allclose(R)
|
||||||
|
|
||||||
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
||||||
def test_unequal(self,shape):
|
def test_unequal(self,shape):
|
||||||
R = Rotation.from_random(shape,rng_seed=1)
|
R = Rotation.from_random(shape,rng_seed=1)
|
||||||
|
@ -1124,3 +1129,7 @@ class TestRotation:
|
||||||
weights_r = np.histogramdd(Eulers_r,steps,rng)[0].flatten(order='F')/N * np.sum(weights)
|
weights_r = np.histogramdd(Eulers_r,steps,rng)[0].flatten(order='F')/N * np.sum(weights)
|
||||||
|
|
||||||
assert np.sqrt(((weights_r - weights) ** 2).mean()) < 5
|
assert np.sqrt(((weights_r - weights) ** 2).mean()) < 5
|
||||||
|
|
||||||
|
def test_mul_invalid(self):
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
Rotation.from_random()*np.ones(3)
|
||||||
|
|
|
@ -28,6 +28,10 @@ class TestVTK:
|
||||||
def _patch_execution_stamp(self, patch_execution_stamp):
|
def _patch_execution_stamp(self, patch_execution_stamp):
|
||||||
print('patched damask.util.execution_stamp')
|
print('patched damask.util.execution_stamp')
|
||||||
|
|
||||||
|
def test_show(sef,default,monkeypatch):
|
||||||
|
monkeypatch.delenv('DISPLAY',raising=False)
|
||||||
|
default.show()
|
||||||
|
|
||||||
def test_rectilinearGrid(self,tmp_path):
|
def test_rectilinearGrid(self,tmp_path):
|
||||||
cells = np.random.randint(5,10,3)*2
|
cells = np.random.randint(5,10,3)*2
|
||||||
size = np.random.random(3) + 1.0
|
size = np.random.random(3) + 1.0
|
||||||
|
|
|
@ -67,5 +67,5 @@ class TestSeeds:
|
||||||
coords = seeds.from_random(size,N_seeds,cells)
|
coords = seeds.from_random(size,N_seeds,cells)
|
||||||
grid = Grid.from_Voronoi_tessellation(cells,size,coords)
|
grid = Grid.from_Voronoi_tessellation(cells,size,coords)
|
||||||
selection=np.random.randint(N_seeds)+1
|
selection=np.random.randint(N_seeds)+1
|
||||||
coords,material = seeds.from_grid(grid,average=average,periodic=periodic,invert=invert,selection=[selection])
|
coords,material = seeds.from_grid(grid,average=average,periodic=periodic,invert_selection=invert,selection=[selection])
|
||||||
assert selection not in material if invert else (selection==material).all()
|
assert selection not in material if invert else (selection==material).all()
|
||||||
|
|
|
@ -14,6 +14,7 @@ module CPFEM
|
||||||
use config
|
use config
|
||||||
use math
|
use math
|
||||||
use rotations
|
use rotations
|
||||||
|
use polynomials
|
||||||
use lattice
|
use lattice
|
||||||
use material
|
use material
|
||||||
use phase
|
use phase
|
||||||
|
@ -32,14 +33,14 @@ module CPFEM
|
||||||
real(pReal), dimension (:,:,:,:), allocatable, private :: &
|
real(pReal), dimension (:,:,:,:), allocatable, private :: &
|
||||||
CPFEM_dcsdE_knownGood !< known good tangent
|
CPFEM_dcsdE_knownGood !< known good tangent
|
||||||
|
|
||||||
integer(pInt), public :: &
|
integer, public :: &
|
||||||
cycleCounter = 0_pInt !< needs description
|
cycleCounter = 0 !< needs description
|
||||||
|
|
||||||
integer(pInt), parameter, public :: &
|
integer, parameter, public :: &
|
||||||
CPFEM_CALCRESULTS = 2_pInt**0_pInt, &
|
CPFEM_CALCRESULTS = 2**0, &
|
||||||
CPFEM_AGERESULTS = 2_pInt**1_pInt, &
|
CPFEM_AGERESULTS = 2**1, &
|
||||||
CPFEM_BACKUPJACOBIAN = 2_pInt**2_pInt, &
|
CPFEM_BACKUPJACOBIAN = 2**2, &
|
||||||
CPFEM_RESTOREJACOBIAN = 2_pInt**3_pInt
|
CPFEM_RESTOREJACOBIAN = 2**3
|
||||||
|
|
||||||
type, private :: tNumerics
|
type, private :: tNumerics
|
||||||
integer :: &
|
integer :: &
|
||||||
|
@ -83,6 +84,7 @@ subroutine CPFEM_initAll
|
||||||
call config_init
|
call config_init
|
||||||
call math_init
|
call math_init
|
||||||
call rotations_init
|
call rotations_init
|
||||||
|
call polynomials_init
|
||||||
call lattice_init
|
call lattice_init
|
||||||
call discretization_marc_init
|
call discretization_marc_init
|
||||||
call material_init(.false.)
|
call material_init(.false.)
|
||||||
|
@ -134,12 +136,12 @@ end subroutine CPFEM_init
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine CPFEM_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyStress, jacobian)
|
subroutine CPFEM_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyStress, jacobian)
|
||||||
|
|
||||||
integer(pInt), intent(in) :: elFE, & !< FE element number
|
integer, intent(in) :: elFE, & !< FE element number
|
||||||
ip !< integration point number
|
ip !< integration point number
|
||||||
real(pReal), intent(in) :: dt !< time increment
|
real(pReal), intent(in) :: dt !< time increment
|
||||||
real(pReal), dimension (3,3), intent(in) :: ffn, & !< deformation gradient for t=t0
|
real(pReal), dimension (3,3), intent(in) :: ffn, & !< deformation gradient for t=t0
|
||||||
ffn1 !< deformation gradient for t=t1
|
ffn1 !< deformation gradient for t=t1
|
||||||
integer(pInt), intent(in) :: mode !< computation mode 1: regular computation plus aging of results
|
integer, intent(in) :: mode !< computation mode 1: regular computation plus aging of results
|
||||||
real(pReal), intent(in) :: temperature_inp !< temperature
|
real(pReal), intent(in) :: temperature_inp !< temperature
|
||||||
real(pReal), dimension(6), intent(out) :: cauchyStress !< stress as 6 vector
|
real(pReal), dimension(6), intent(out) :: cauchyStress !< stress as 6 vector
|
||||||
real(pReal), dimension(6,6), intent(out) :: jacobian !< jacobian as 66 tensor (Consistent tangent dcs/dE)
|
real(pReal), dimension(6,6), intent(out) :: jacobian !< jacobian as 66 tensor (Consistent tangent dcs/dE)
|
||||||
|
@ -150,7 +152,7 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyS
|
||||||
real(pReal), dimension (3,3,3,3) :: H_sym, &
|
real(pReal), dimension (3,3,3,3) :: H_sym, &
|
||||||
H
|
H
|
||||||
|
|
||||||
integer(pInt) elCP, & ! crystal plasticity element number
|
integer elCP, & ! crystal plasticity element number
|
||||||
i, j, k, l, m, n, ph, homog, mySource,ce
|
i, j, k, l, m, n, ph, homog, mySource,ce
|
||||||
|
|
||||||
real(pReal), parameter :: ODD_STRESS = 1e15_pReal, & !< return value for stress if terminallyIll
|
real(pReal), parameter :: ODD_STRESS = 1e15_pReal, & !< return value for stress if terminallyIll
|
||||||
|
@ -171,17 +173,17 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyS
|
||||||
print'(a,/)', '#############################################'; flush (6)
|
print'(a,/)', '#############################################'; flush (6)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if (iand(mode, CPFEM_BACKUPJACOBIAN) /= 0_pInt) &
|
if (iand(mode, CPFEM_BACKUPJACOBIAN) /= 0) &
|
||||||
CPFEM_dcsde_knownGood = CPFEM_dcsde
|
CPFEM_dcsde_knownGood = CPFEM_dcsde
|
||||||
if (iand(mode, CPFEM_RESTOREJACOBIAN) /= 0_pInt) &
|
if (iand(mode, CPFEM_RESTOREJACOBIAN) /= 0) &
|
||||||
CPFEM_dcsde = CPFEM_dcsde_knownGood
|
CPFEM_dcsde = CPFEM_dcsde_knownGood
|
||||||
|
|
||||||
if (iand(mode, CPFEM_AGERESULTS) /= 0_pInt) call CPFEM_forward
|
if (iand(mode, CPFEM_AGERESULTS) /= 0) call CPFEM_forward
|
||||||
|
|
||||||
homogenization_F0(1:3,1:3,ce) = ffn
|
homogenization_F0(1:3,1:3,ce) = ffn
|
||||||
homogenization_F(1:3,1:3,ce) = ffn1
|
homogenization_F(1:3,1:3,ce) = ffn1
|
||||||
|
|
||||||
if (iand(mode, CPFEM_CALCRESULTS) /= 0_pInt) then
|
if (iand(mode, CPFEM_CALCRESULTS) /= 0) then
|
||||||
|
|
||||||
validCalculation: if (terminallyIll) then
|
validCalculation: if (terminallyIll) then
|
||||||
call random_number(rnd)
|
call random_number(rnd)
|
||||||
|
@ -264,7 +266,7 @@ end subroutine CPFEM_forward
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine CPFEM_results(inc,time)
|
subroutine CPFEM_results(inc,time)
|
||||||
|
|
||||||
integer(pInt), intent(in) :: inc
|
integer, intent(in) :: inc
|
||||||
real(pReal), intent(in) :: time
|
real(pReal), intent(in) :: time
|
||||||
|
|
||||||
call results_openJobFile
|
call results_openJobFile
|
||||||
|
|
|
@ -16,6 +16,7 @@ module CPFEM2
|
||||||
use config
|
use config
|
||||||
use math
|
use math
|
||||||
use rotations
|
use rotations
|
||||||
|
use polynomials
|
||||||
use lattice
|
use lattice
|
||||||
use material
|
use material
|
||||||
use phase
|
use phase
|
||||||
|
@ -57,6 +58,7 @@ subroutine CPFEM_initAll
|
||||||
call config_init
|
call config_init
|
||||||
call math_init
|
call math_init
|
||||||
call rotations_init
|
call rotations_init
|
||||||
|
call polynomials_init
|
||||||
call lattice_init
|
call lattice_init
|
||||||
#if defined(MESH)
|
#if defined(MESH)
|
||||||
call discretization_mesh_init(restart=interface_restartInc>0)
|
call discretization_mesh_init(restart=interface_restartInc>0)
|
||||||
|
|
|
@ -223,9 +223,9 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, &
|
||||||
integer :: computationMode, i, node, CPnodeID
|
integer :: computationMode, i, node, CPnodeID
|
||||||
integer(pI32) :: defaultNumThreadsInt !< default value set by Marc
|
integer(pI32) :: defaultNumThreadsInt !< default value set by Marc
|
||||||
|
|
||||||
integer(pInt), save :: &
|
integer, save :: &
|
||||||
theInc = -1_pInt, & !< needs description
|
theInc = -1, & !< needs description
|
||||||
lastLovl = 0_pInt !< lovl in previous call to marc hypela2
|
lastLovl = 0 !< lovl in previous call to marc hypela2
|
||||||
real(pReal), save :: &
|
real(pReal), save :: &
|
||||||
theTime = 0.0_pReal, & !< needs description
|
theTime = 0.0_pReal, & !< needs description
|
||||||
theDelta = 0.0_pReal
|
theDelta = 0.0_pReal
|
||||||
|
|
|
@ -1862,8 +1862,8 @@ subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_
|
||||||
|
|
||||||
integer, dimension(worldsize) :: &
|
integer, dimension(worldsize) :: &
|
||||||
readSize !< contribution of all processes
|
readSize !< contribution of all processes
|
||||||
integer :: ierr
|
|
||||||
integer :: hdferr
|
integer :: hdferr
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
!-------------------------------------------------------------------------------------------------
|
!-------------------------------------------------------------------------------------------------
|
||||||
! creating a property list for transfer properties (is collective for MPI)
|
! creating a property list for transfer properties (is collective for MPI)
|
||||||
|
@ -1877,8 +1877,8 @@ subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_
|
||||||
if (parallel) then
|
if (parallel) then
|
||||||
call H5Pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr)
|
call H5Pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
call MPI_allreduce(MPI_IN_PLACE,readSize,worldsize,MPI_INT,MPI_SUM,PETSC_COMM_WORLD,ierr) ! get total output size over each process
|
call MPI_allreduce(MPI_IN_PLACE,readSize,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,err_MPI) ! get total output size over each process
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
end if
|
end if
|
||||||
#endif
|
#endif
|
||||||
myStart = int(0,HSIZE_T)
|
myStart = int(0,HSIZE_T)
|
||||||
|
@ -1956,7 +1956,8 @@ subroutine initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
|
||||||
|
|
||||||
integer, dimension(worldsize) :: writeSize !< contribution of all processes
|
integer, dimension(worldsize) :: writeSize !< contribution of all processes
|
||||||
integer(HID_T) :: dcpl
|
integer(HID_T) :: dcpl
|
||||||
integer :: ierr, hdferr
|
integer :: hdferr
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
integer(HSIZE_T), parameter :: chunkSize = 1024_HSIZE_T**2/8_HSIZE_T
|
integer(HSIZE_T), parameter :: chunkSize = 1024_HSIZE_T**2/8_HSIZE_T
|
||||||
|
|
||||||
|
|
||||||
|
@ -1977,8 +1978,8 @@ subroutine initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
|
||||||
writeSize(worldrank+1) = int(myShape(ubound(myShape,1)))
|
writeSize(worldrank+1) = int(myShape(ubound(myShape,1)))
|
||||||
#ifdef PETSC
|
#ifdef PETSC
|
||||||
if (parallel) then
|
if (parallel) then
|
||||||
call MPI_allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INT,MPI_SUM,PETSC_COMM_WORLD,ierr) ! get total output size over each process
|
call MPI_allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,err_MPI) ! get total output size over each process
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
end if
|
end if
|
||||||
#endif
|
#endif
|
||||||
myStart = int(0,HSIZE_T)
|
myStart = int(0,HSIZE_T)
|
||||||
|
|
|
@ -191,8 +191,10 @@ logical function isScalar(line)
|
||||||
|
|
||||||
character(len=*), intent(in) :: line
|
character(len=*), intent(in) :: line
|
||||||
|
|
||||||
isScalar = (.not.isKeyValue(line) .and. .not.isKey(line) .and. .not.isListItem(line) &
|
isScalar = (.not. isKeyValue(line) .and. &
|
||||||
.and. .not.isFlow(line))
|
.not. isKey(line) .and. &
|
||||||
|
.not. isListItem(line) .and. &
|
||||||
|
.not. isFlow(line))
|
||||||
|
|
||||||
end function isScalar
|
end function isScalar
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,8 @@ module YAML_types
|
||||||
tNode_get_byKey_as1dString => tNode_get_byKey_as1dString
|
tNode_get_byKey_as1dString => tNode_get_byKey_as1dString
|
||||||
procedure :: &
|
procedure :: &
|
||||||
getKey => tNode_get_byIndex_asKey
|
getKey => tNode_get_byIndex_asKey
|
||||||
|
procedure :: &
|
||||||
|
Keys => tNode_getKeys
|
||||||
procedure :: &
|
procedure :: &
|
||||||
getIndex => tNode_get_byKey_asIndex
|
getIndex => tNode_get_byKey_asIndex
|
||||||
procedure :: &
|
procedure :: &
|
||||||
|
@ -117,7 +119,7 @@ module YAML_types
|
||||||
|
|
||||||
type, extends(tNode), public :: tList
|
type, extends(tNode), public :: tList
|
||||||
|
|
||||||
class(tItem), pointer :: first => null()
|
class(tItem), pointer :: first => NULL()
|
||||||
|
|
||||||
contains
|
contains
|
||||||
procedure :: asFormattedString => tList_asFormattedString
|
procedure :: asFormattedString => tList_asFormattedString
|
||||||
|
@ -144,8 +146,8 @@ module YAML_types
|
||||||
|
|
||||||
type :: tItem
|
type :: tItem
|
||||||
character(len=:), allocatable :: key
|
character(len=:), allocatable :: key
|
||||||
class(tNode), pointer :: node => null()
|
class(tNode), pointer :: node => NULL()
|
||||||
class(tItem), pointer :: next => null()
|
class(tItem), pointer :: next => NULL()
|
||||||
|
|
||||||
contains
|
contains
|
||||||
final :: tItem_finalize
|
final :: tItem_finalize
|
||||||
|
@ -332,9 +334,12 @@ function tNode_asScalar(self) result(scalar)
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in), target :: self
|
||||||
class(tScalar), pointer :: scalar
|
class(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
select type(self)
|
select type(self)
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => self
|
scalar => self
|
||||||
|
class default
|
||||||
|
nullify(scalar)
|
||||||
end select
|
end select
|
||||||
|
|
||||||
end function tNode_asScalar
|
end function tNode_asScalar
|
||||||
|
@ -348,9 +353,12 @@ function tNode_asList(self) result(list)
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in), target :: self
|
||||||
class(tList), pointer :: list
|
class(tList), pointer :: list
|
||||||
|
|
||||||
|
|
||||||
select type(self)
|
select type(self)
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => self
|
list => self
|
||||||
|
class default
|
||||||
|
nullify(list)
|
||||||
end select
|
end select
|
||||||
|
|
||||||
end function tNode_asList
|
end function tNode_asList
|
||||||
|
@ -364,9 +372,12 @@ function tNode_asDict(self) result(dict)
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in), target :: self
|
||||||
class(tDict), pointer :: dict
|
class(tDict), pointer :: dict
|
||||||
|
|
||||||
|
|
||||||
select type(self)
|
select type(self)
|
||||||
class is(tDict)
|
class is(tDict)
|
||||||
dict => self
|
dict => self
|
||||||
|
class default
|
||||||
|
nullify(dict)
|
||||||
end select
|
end select
|
||||||
|
|
||||||
end function tNode_asDict
|
end function tNode_asDict
|
||||||
|
@ -385,6 +396,7 @@ function tNode_get_byIndex(self,i) result(node)
|
||||||
class(tItem), pointer :: item
|
class(tItem), pointer :: item
|
||||||
integer :: j
|
integer :: j
|
||||||
|
|
||||||
|
|
||||||
select type(self)
|
select type(self)
|
||||||
class is(tList)
|
class is(tList)
|
||||||
self_ => self%asList()
|
self_ => self%asList()
|
||||||
|
@ -409,15 +421,14 @@ end function tNode_get_byIndex
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_asFloat(self,i) result(nodeAsFloat)
|
function tNode_get_byIndex_asFloat(self,i) result(nodeAsFloat)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
real(pReal) :: nodeAsFloat
|
real(pReal) :: nodeAsFloat
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsFloat = scalar%asFloat()
|
nodeAsFloat = scalar%asFloat()
|
||||||
|
@ -433,15 +444,15 @@ end function tNode_get_byIndex_asFloat
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_asInt(self,i) result(nodeAsInt)
|
function tNode_get_byIndex_asInt(self,i) result(nodeAsInt)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
integer :: nodeAsInt
|
integer :: nodeAsInt
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
class(tNode), pointer :: node
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsInt = scalar%asInt()
|
nodeAsInt = scalar%asInt()
|
||||||
|
@ -457,15 +468,14 @@ end function tNode_get_byIndex_asInt
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_asBool(self,i) result(nodeAsBool)
|
function tNode_get_byIndex_asBool(self,i) result(nodeAsBool)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
logical :: nodeAsBool
|
logical :: nodeAsBool
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsBool = scalar%asBool()
|
nodeAsBool = scalar%asBool()
|
||||||
|
@ -481,15 +491,14 @@ end function tNode_get_byIndex_asBool
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_asString(self,i) result(nodeAsString)
|
function tNode_get_byIndex_asString(self,i) result(nodeAsString)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
character(len=:), allocatable :: nodeAsString
|
character(len=:), allocatable :: nodeAsString
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsString = scalar%asString()
|
nodeAsString = scalar%asString()
|
||||||
|
@ -505,15 +514,14 @@ end function tNode_get_byIndex_asString
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_as1dFloat(self,i) result(nodeAs1dFloat)
|
function tNode_get_byIndex_as1dFloat(self,i) result(nodeAs1dFloat)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
real(pReal), dimension(:), allocatable :: nodeAs1dFloat
|
real(pReal), dimension(:), allocatable :: nodeAs1dFloat
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
class(tList), pointer :: list
|
class(tList), pointer :: list
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dFloat = list%as1dFloat()
|
nodeAs1dFloat = list%as1dFloat()
|
||||||
|
@ -529,15 +537,14 @@ end function tNode_get_byIndex_as1dFloat
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_as1dInt(self,i) result(nodeAs1dInt)
|
function tNode_get_byIndex_as1dInt(self,i) result(nodeAs1dInt)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
integer, dimension(:), allocatable :: nodeAs1dInt
|
integer, dimension(:), allocatable :: nodeAs1dInt
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
class(tList), pointer :: list
|
class(tList), pointer :: list
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dInt = list%as1dInt()
|
nodeAs1dInt = list%as1dInt()
|
||||||
|
@ -553,15 +560,14 @@ end function tNode_get_byIndex_as1dInt
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_as1dBool(self,i) result(nodeAs1dBool)
|
function tNode_get_byIndex_as1dBool(self,i) result(nodeAs1dBool)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
logical, dimension(:), allocatable :: nodeAs1dBool
|
logical, dimension(:), allocatable :: nodeAs1dBool
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
class(tList), pointer :: list
|
class(tList), pointer :: list
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dBool = list%as1dBool()
|
nodeAs1dBool = list%as1dBool()
|
||||||
|
@ -577,15 +583,14 @@ end function tNode_get_byIndex_as1dBool
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byIndex_as1dString(self,i) result(nodeAs1dString)
|
function tNode_get_byIndex_as1dString(self,i) result(nodeAs1dString)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
integer, intent(in) :: i
|
integer, intent(in) :: i
|
||||||
character(len=:), allocatable, dimension(:) :: nodeAs1dString
|
character(len=:), allocatable, dimension(:) :: nodeAs1dString
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tList), pointer :: list
|
type(tList), pointer :: list
|
||||||
|
|
||||||
node => self%get(i)
|
|
||||||
select type(node)
|
select type(node => self%get(i))
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dString = list%as1dString()
|
nodeAs1dString = list%as1dString()
|
||||||
|
@ -609,6 +614,7 @@ function tNode_get_byIndex_asKey(self,i) result(key)
|
||||||
type(tDict), pointer :: dict
|
type(tDict), pointer :: dict
|
||||||
type(tItem), pointer :: item
|
type(tItem), pointer :: item
|
||||||
|
|
||||||
|
|
||||||
select type(self)
|
select type(self)
|
||||||
class is(tDict)
|
class is(tDict)
|
||||||
dict => self%asDict()
|
dict => self%asDict()
|
||||||
|
@ -625,6 +631,33 @@ function tNode_get_byIndex_asKey(self,i) result(key)
|
||||||
end function tNode_get_byIndex_asKey
|
end function tNode_get_byIndex_asKey
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @brief Get all keys from a dictionary
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
function tNode_getKeys(self) result(keys)
|
||||||
|
|
||||||
|
class(tNode), intent(in) :: self
|
||||||
|
character(len=:), dimension(:), allocatable :: keys
|
||||||
|
|
||||||
|
character(len=pStringLen), dimension(:), allocatable :: temp
|
||||||
|
integer :: j, l
|
||||||
|
|
||||||
|
|
||||||
|
allocate(temp(self%length))
|
||||||
|
l = 0
|
||||||
|
do j = 1, self%length
|
||||||
|
temp(j) = self%getKey(j)
|
||||||
|
l = max(len_trim(temp(j)),l)
|
||||||
|
end do
|
||||||
|
|
||||||
|
allocate(character(l)::keys(self%length))
|
||||||
|
do j = 1, self%length
|
||||||
|
keys(j) = trim(temp(j))
|
||||||
|
end do
|
||||||
|
|
||||||
|
end function tNode_getKeys
|
||||||
|
|
||||||
|
|
||||||
!-------------------------------------------------------------------------------------------------
|
!-------------------------------------------------------------------------------------------------
|
||||||
!> @brief Checks if a given key/item is present in the dict/list
|
!> @brief Checks if a given key/item is present in the dict/list
|
||||||
!-------------------------------------------------------------------------------------------------
|
!-------------------------------------------------------------------------------------------------
|
||||||
|
@ -713,17 +746,16 @@ end function tNode_get_byKey
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_asFloat(self,k,defaultVal) result(nodeAsFloat)
|
function tNode_get_byKey_asFloat(self,k,defaultVal) result(nodeAsFloat)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
real(pReal), intent(in), optional :: defaultVal
|
real(pReal), intent(in), optional :: defaultVal
|
||||||
real(pReal) :: nodeAsFloat
|
real(pReal) :: nodeAsFloat
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsFloat = scalar%asFloat()
|
nodeAsFloat = scalar%asFloat()
|
||||||
|
@ -744,17 +776,16 @@ end function tNode_get_byKey_asFloat
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_asInt(self,k,defaultVal) result(nodeAsInt)
|
function tNode_get_byKey_asInt(self,k,defaultVal) result(nodeAsInt)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
integer, intent(in), optional :: defaultVal
|
integer, intent(in), optional :: defaultVal
|
||||||
integer :: nodeAsInt
|
integer :: nodeAsInt
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsInt = scalar%asInt()
|
nodeAsInt = scalar%asInt()
|
||||||
|
@ -775,17 +806,16 @@ end function tNode_get_byKey_asInt
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_asBool(self,k,defaultVal) result(nodeAsBool)
|
function tNode_get_byKey_asBool(self,k,defaultVal) result(nodeAsBool)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
logical, intent(in), optional :: defaultVal
|
logical, intent(in), optional :: defaultVal
|
||||||
logical :: nodeAsBool
|
logical :: nodeAsBool
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsBool = scalar%asBool()
|
nodeAsBool = scalar%asBool()
|
||||||
|
@ -806,17 +836,16 @@ end function tNode_get_byKey_asBool
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_asString(self,k,defaultVal) result(nodeAsString)
|
function tNode_get_byKey_asString(self,k,defaultVal) result(nodeAsString)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
character(len=*), intent(in), optional :: defaultVal
|
character(len=*), intent(in), optional :: defaultVal
|
||||||
character(len=:), allocatable :: nodeAsString
|
character(len=:), allocatable :: nodeAsString
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tScalar)
|
class is(tScalar)
|
||||||
scalar => node%asScalar()
|
scalar => node%asScalar()
|
||||||
nodeAsString = scalar%asString()
|
nodeAsString = scalar%asString()
|
||||||
|
@ -837,19 +866,18 @@ end function tNode_get_byKey_asString
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_as1dFloat(self,k,defaultVal,requiredSize) result(nodeAs1dFloat)
|
function tNode_get_byKey_as1dFloat(self,k,defaultVal,requiredSize) result(nodeAs1dFloat)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
real(pReal), intent(in), dimension(:), optional :: defaultVal
|
real(pReal), intent(in), dimension(:), optional :: defaultVal
|
||||||
integer, intent(in), optional :: requiredSize
|
integer, intent(in), optional :: requiredSize
|
||||||
|
|
||||||
real(pReal), dimension(:), allocatable :: nodeAs1dFloat
|
real(pReal), dimension(:), allocatable :: nodeAs1dFloat
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tList), pointer :: list
|
type(tList), pointer :: list
|
||||||
|
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dFloat = list%as1dFloat()
|
nodeAs1dFloat = list%as1dFloat()
|
||||||
|
@ -874,19 +902,18 @@ end function tNode_get_byKey_as1dFloat
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_as2dFloat(self,k,defaultVal,requiredShape) result(nodeAs2dFloat)
|
function tNode_get_byKey_as2dFloat(self,k,defaultVal,requiredShape) result(nodeAs2dFloat)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
real(pReal), intent(in), dimension(:,:), optional :: defaultVal
|
real(pReal), intent(in), dimension(:,:), optional :: defaultVal
|
||||||
integer, intent(in), dimension(2), optional :: requiredShape
|
integer, intent(in), dimension(2), optional :: requiredShape
|
||||||
|
|
||||||
real(pReal), dimension(:,:), allocatable :: nodeAs2dFloat
|
real(pReal), dimension(:,:), allocatable :: nodeAs2dFloat
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tList), pointer :: rows
|
type(tList), pointer :: rows
|
||||||
|
|
||||||
|
|
||||||
if(self%contains(k)) then
|
if(self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tList)
|
class is(tList)
|
||||||
rows => node%asList()
|
rows => node%asList()
|
||||||
nodeAs2dFloat = rows%as2dFloat()
|
nodeAs2dFloat = rows%as2dFloat()
|
||||||
|
@ -911,18 +938,16 @@ end function tNode_get_byKey_as2dFloat
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_as1dInt(self,k,defaultVal,requiredSize) result(nodeAs1dInt)
|
function tNode_get_byKey_as1dInt(self,k,defaultVal,requiredSize) result(nodeAs1dInt)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
integer, dimension(:), intent(in), optional :: defaultVal
|
integer, dimension(:), intent(in), optional :: defaultVal
|
||||||
integer, intent(in), optional :: requiredSize
|
integer, intent(in), optional :: requiredSize
|
||||||
integer, dimension(:), allocatable :: nodeAs1dInt
|
integer, dimension(:), allocatable :: nodeAs1dInt
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tList), pointer :: list
|
type(tList), pointer :: list
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dInt = list%as1dInt()
|
nodeAs1dInt = list%as1dInt()
|
||||||
|
@ -947,17 +972,16 @@ end function tNode_get_byKey_as1dInt
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_as1dBool(self,k,defaultVal) result(nodeAs1dBool)
|
function tNode_get_byKey_as1dBool(self,k,defaultVal) result(nodeAs1dBool)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
logical, dimension(:), intent(in), optional :: defaultVal
|
logical, dimension(:), intent(in), optional :: defaultVal
|
||||||
logical, dimension(:), allocatable :: nodeAs1dBool
|
logical, dimension(:), allocatable :: nodeAs1dBool
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tList), pointer :: list
|
type(tList), pointer :: list
|
||||||
|
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dBool = list%as1dBool()
|
nodeAs1dBool = list%as1dBool()
|
||||||
|
@ -978,17 +1002,16 @@ end function tNode_get_byKey_as1dBool
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function tNode_get_byKey_as1dString(self,k,defaultVal) result(nodeAs1dString)
|
function tNode_get_byKey_as1dString(self,k,defaultVal) result(nodeAs1dString)
|
||||||
|
|
||||||
class(tNode), intent(in), target :: self
|
class(tNode), intent(in) :: self
|
||||||
character(len=*), intent(in) :: k
|
character(len=*), intent(in) :: k
|
||||||
character(len=*), intent(in), dimension(:), optional :: defaultVal
|
character(len=*), intent(in), dimension(:), optional :: defaultVal
|
||||||
character(len=:), allocatable, dimension(:) :: nodeAs1dString
|
character(len=:), allocatable, dimension(:) :: nodeAs1dString
|
||||||
|
|
||||||
class(tNode), pointer :: node
|
|
||||||
type(tList), pointer :: list
|
type(tList), pointer :: list
|
||||||
|
|
||||||
|
|
||||||
if (self%contains(k)) then
|
if (self%contains(k)) then
|
||||||
node => self%get(k)
|
select type(node => self%get(k))
|
||||||
select type(node)
|
|
||||||
class is(tList)
|
class is(tList)
|
||||||
list => node%asList()
|
list => node%asList()
|
||||||
nodeAs1dString = list%as1dString()
|
nodeAs1dString = list%as1dString()
|
||||||
|
@ -1190,6 +1213,7 @@ function tList_as1dFloat(self)
|
||||||
type(tItem), pointer :: item
|
type(tItem), pointer :: item
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
allocate(tList_as1dFloat(self%length))
|
allocate(tList_as1dFloat(self%length))
|
||||||
item => self%first
|
item => self%first
|
||||||
do i = 1, self%length
|
do i = 1, self%length
|
||||||
|
@ -1213,6 +1237,7 @@ function tList_as2dFloat(self)
|
||||||
class(tNode), pointer :: row
|
class(tNode), pointer :: row
|
||||||
type(tList), pointer :: row_data
|
type(tList), pointer :: row_data
|
||||||
|
|
||||||
|
|
||||||
row => self%get(1)
|
row => self%get(1)
|
||||||
row_data => row%asList()
|
row_data => row%asList()
|
||||||
allocate(tList_as2dFloat(self%length,row_data%length))
|
allocate(tList_as2dFloat(self%length,row_data%length))
|
||||||
|
@ -1239,6 +1264,7 @@ function tList_as1dInt(self)
|
||||||
type(tItem), pointer :: item
|
type(tItem), pointer :: item
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
allocate(tList_as1dInt(self%length))
|
allocate(tList_as1dInt(self%length))
|
||||||
item => self%first
|
item => self%first
|
||||||
do i = 1, self%length
|
do i = 1, self%length
|
||||||
|
@ -1262,6 +1288,7 @@ function tList_as1dBool(self)
|
||||||
type(tItem), pointer :: item
|
type(tItem), pointer :: item
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
allocate(tList_as1dBool(self%length))
|
allocate(tList_as1dBool(self%length))
|
||||||
item => self%first
|
item => self%first
|
||||||
do i = 1, self%length
|
do i = 1, self%length
|
||||||
|
@ -1285,6 +1312,7 @@ function tList_as1dString(self)
|
||||||
type(tItem), pointer :: item
|
type(tItem), pointer :: item
|
||||||
type(tScalar), pointer :: scalar
|
type(tScalar), pointer :: scalar
|
||||||
|
|
||||||
|
|
||||||
len_max = 0
|
len_max = 0
|
||||||
item => self%first
|
item => self%first
|
||||||
do i = 1, self%length
|
do i = 1, self%length
|
||||||
|
|
|
@ -151,7 +151,7 @@ pure logical function validBase64(base64_str)
|
||||||
l = len(base64_str,pI64)
|
l = len(base64_str,pI64)
|
||||||
validBase64 = .true.
|
validBase64 = .true.
|
||||||
|
|
||||||
if(mod(l,4_pI64)/=0_pI64 .or. l < 4_pInt) validBase64 = .false.
|
if(mod(l,4_pI64)/=0_pI64 .or. l < 4_pI64) validBase64 = .false.
|
||||||
if(verify(base64_str(:l-2_pI64),base64_encoding, kind=pI64) /= 0_pI64) validBase64 = .false.
|
if(verify(base64_str(:l-2_pI64),base64_encoding, kind=pI64) /= 0_pI64) validBase64 = .false.
|
||||||
if(verify(base64_str(l-1_pI64:),base64_encoding//'=',kind=pI64) /= 0_pI64) validBase64 = .false.
|
if(verify(base64_str(l-1_pI64:),base64_encoding//'=',kind=pI64) /= 0_pI64) validBase64 = .false.
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "LAPACK_interface.f90"
|
#include "LAPACK_interface.f90"
|
||||||
#include "math.f90"
|
#include "math.f90"
|
||||||
#include "rotations.f90"
|
#include "rotations.f90"
|
||||||
|
#include "polynomials.f90"
|
||||||
#include "lattice.f90"
|
#include "lattice.f90"
|
||||||
#include "element.f90"
|
#include "element.f90"
|
||||||
#include "geometry_plastic_nonlocal.f90"
|
#include "geometry_plastic_nonlocal.f90"
|
||||||
|
|
|
@ -75,7 +75,6 @@ program DAMASK_grid
|
||||||
integer :: &
|
integer :: &
|
||||||
i, j, m, field, &
|
i, j, m, field, &
|
||||||
errorID = 0, &
|
errorID = 0, &
|
||||||
ierr,&
|
|
||||||
cutBackLevel = 0, & !< cut back level \f$ t = \frac{t_{inc}}{2^l} \f$
|
cutBackLevel = 0, & !< cut back level \f$ t = \frac{t_{inc}}{2^l} \f$
|
||||||
stepFraction = 0, & !< fraction of current time interval
|
stepFraction = 0, & !< fraction of current time interval
|
||||||
l = 0, & !< current load case
|
l = 0, & !< current load case
|
||||||
|
@ -86,6 +85,7 @@ program DAMASK_grid
|
||||||
nActiveFields = 0, &
|
nActiveFields = 0, &
|
||||||
maxCutBack, & !< max number of cut backs
|
maxCutBack, & !< max number of cut backs
|
||||||
stagItMax !< max number of field level staggered iterations
|
stagItMax !< max number of field level staggered iterations
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
character(len=pStringLen) :: &
|
character(len=pStringLen) :: &
|
||||||
incInfo
|
incInfo
|
||||||
|
|
||||||
|
@ -455,23 +455,23 @@ program DAMASK_grid
|
||||||
print'(/,1x,a,i0,a)', 'increment ', totalIncsCounter, ' NOT converged'
|
print'(/,1x,a,i0,a)', 'increment ', totalIncsCounter, ' NOT converged'
|
||||||
endif; flush(IO_STDOUT)
|
endif; flush(IO_STDOUT)
|
||||||
|
|
||||||
call MPI_Allreduce(interface_SIGUSR1,signal,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(interface_SIGUSR1,signal,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
if (mod(inc,loadCases(l)%f_out) == 0 .or. signal) then
|
if (mod(inc,loadCases(l)%f_out) == 0 .or. signal) then
|
||||||
print'(/,1x,a)', '... writing results to file ...............................................'
|
print'(/,1x,a)', '... writing results to file ...............................................'
|
||||||
flush(IO_STDOUT)
|
flush(IO_STDOUT)
|
||||||
call CPFEM_results(totalIncsCounter,t)
|
call CPFEM_results(totalIncsCounter,t)
|
||||||
endif
|
endif
|
||||||
if (signal) call interface_setSIGUSR1(.false.)
|
if (signal) call interface_setSIGUSR1(.false.)
|
||||||
call MPI_Allreduce(interface_SIGUSR2,signal,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(interface_SIGUSR2,signal,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
if (mod(inc,loadCases(l)%f_restart) == 0 .or. signal) then
|
if (mod(inc,loadCases(l)%f_restart) == 0 .or. signal) then
|
||||||
call mechanical_restartWrite
|
call mechanical_restartWrite
|
||||||
call CPFEM_restartWrite
|
call CPFEM_restartWrite
|
||||||
endif
|
endif
|
||||||
if (signal) call interface_setSIGUSR2(.false.)
|
if (signal) call interface_setSIGUSR2(.false.)
|
||||||
call MPI_Allreduce(interface_SIGTERM,signal,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(interface_SIGTERM,signal,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
if (signal) exit loadCaseLooping
|
if (signal) exit loadCaseLooping
|
||||||
endif skipping
|
endif skipping
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,8 @@ subroutine discretization_grid_init(restart)
|
||||||
|
|
||||||
integer :: &
|
integer :: &
|
||||||
j, &
|
j, &
|
||||||
debug_element, debug_ip, &
|
debug_element, debug_ip
|
||||||
ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
integer(C_INTPTR_T) :: &
|
integer(C_INTPTR_T) :: &
|
||||||
devNull, z, z_offset
|
devNull, z, z_offset
|
||||||
integer, dimension(worldsize) :: &
|
integer, dimension(worldsize) :: &
|
||||||
|
@ -88,13 +88,13 @@ subroutine discretization_grid_init(restart)
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
|
||||||
call MPI_Bcast(grid,3,MPI_INTEGER,0,MPI_COMM_WORLD, ierr)
|
call MPI_Bcast(grid,3_MPI_INTEGER_KIND,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD, err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
if (grid(1) < 2) call IO_error(844, ext_msg='cells(1) must be larger than 1')
|
if (grid(1) < 2) call IO_error(844, ext_msg='cells(1) must be larger than 1')
|
||||||
call MPI_Bcast(geomSize,3,MPI_DOUBLE,0,MPI_COMM_WORLD, ierr)
|
call MPI_Bcast(geomSize,3_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD, err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call MPI_Bcast(origin,3,MPI_DOUBLE,0,MPI_COMM_WORLD, ierr)
|
call MPI_Bcast(origin,3_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD, err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
print'(/,1x,a,3(i12,1x))', 'cells a b c: ', grid
|
print'(/,1x,a,3(i12,1x))', 'cells a b c: ', grid
|
||||||
print '(1x,a,3(es12.5,1x))', 'size x y z: ', geomSize
|
print '(1x,a,3(es12.5,1x))', 'size x y z: ', geomSize
|
||||||
|
@ -118,14 +118,17 @@ subroutine discretization_grid_init(restart)
|
||||||
myGrid = [grid(1:2),grid3]
|
myGrid = [grid(1:2),grid3]
|
||||||
mySize = [geomSize(1:2),size3]
|
mySize = [geomSize(1:2),size3]
|
||||||
|
|
||||||
call MPI_Gather(product(grid(1:2))*grid3Offset,1,MPI_INTEGER,displs, 1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
|
call MPI_Gather(product(grid(1:2))*grid3Offset, 1_MPI_INTEGER_KIND,MPI_INTEGER,displs,&
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
1_MPI_INTEGER_KIND,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
call MPI_Gather(product(myGrid), 1,MPI_INTEGER,sendcounts,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
call MPI_Gather(product(myGrid), 1_MPI_INTEGER_KIND,MPI_INTEGER,sendcounts,&
|
||||||
|
1_MPI_INTEGER_KIND,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
allocate(materialAt(product(myGrid)))
|
allocate(materialAt(product(myGrid)))
|
||||||
call MPI_Scatterv(materialAt_global,sendcounts,displs,MPI_INTEGER,materialAt,size(materialAt),MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
|
call MPI_Scatterv(materialAt_global,sendcounts,displs,MPI_INTEGER,materialAt,size(materialAt),&
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
call discretization_init(materialAt, &
|
call discretization_init(materialAt, &
|
||||||
IPcoordinates0(myGrid,mySize,grid3Offset), &
|
IPcoordinates0(myGrid,mySize,grid3Offset), &
|
||||||
|
@ -307,7 +310,7 @@ subroutine readVTI(grid,geomSize,origin,material, &
|
||||||
case('Float64')
|
case('Float64')
|
||||||
as_Int = int(prec_bytesToC_DOUBLE (asBytes(base64_str,headerType,compressed)))
|
as_Int = int(prec_bytesToC_DOUBLE (asBytes(base64_str,headerType,compressed)))
|
||||||
case default
|
case default
|
||||||
call IO_error(844_pInt,ext_msg='unknown data type: '//trim(dataType))
|
call IO_error(844,ext_msg='unknown data type: '//trim(dataType))
|
||||||
end select
|
end select
|
||||||
|
|
||||||
end function as_Int
|
end function as_Int
|
||||||
|
@ -335,7 +338,7 @@ subroutine readVTI(grid,geomSize,origin,material, &
|
||||||
case('Float64')
|
case('Float64')
|
||||||
as_pReal = real(prec_bytesToC_DOUBLE (asBytes(base64_str,headerType,compressed)),pReal)
|
as_pReal = real(prec_bytesToC_DOUBLE (asBytes(base64_str,headerType,compressed)),pReal)
|
||||||
case default
|
case default
|
||||||
call IO_error(844_pInt,ext_msg='unknown data type: '//trim(dataType))
|
call IO_error(844,ext_msg='unknown data type: '//trim(dataType))
|
||||||
end select
|
end select
|
||||||
|
|
||||||
end function as_pReal
|
end function as_pReal
|
||||||
|
|
|
@ -39,9 +39,8 @@ module grid_damage_spectral
|
||||||
type(tSolutionParams) :: params
|
type(tSolutionParams) :: params
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc data
|
! PETSc data
|
||||||
SNES :: damage_snes
|
SNES :: SNES_damage
|
||||||
Vec :: solution_vec
|
Vec :: solution_vec
|
||||||
PetscInt :: xstart, xend, ystart, yend, zstart, zend
|
|
||||||
real(pReal), dimension(:,:,:), allocatable :: &
|
real(pReal), dimension(:,:,:), allocatable :: &
|
||||||
phi_current, & !< field of current damage
|
phi_current, & !< field of current damage
|
||||||
phi_lastInc, & !< field of previous damage
|
phi_lastInc, & !< field of previous damage
|
||||||
|
@ -69,7 +68,8 @@ subroutine grid_damage_spectral_init()
|
||||||
PetscInt, dimension(0:worldsize-1) :: localK
|
PetscInt, dimension(0:worldsize-1) :: localK
|
||||||
DM :: damage_grid
|
DM :: damage_grid
|
||||||
Vec :: uBound, lBound
|
Vec :: uBound, lBound
|
||||||
PetscErrorCode :: ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
PetscErrorCode :: err_PETSc
|
||||||
class(tNode), pointer :: &
|
class(tNode), pointer :: &
|
||||||
num_grid, &
|
num_grid, &
|
||||||
num_generic
|
num_generic
|
||||||
|
@ -99,60 +99,71 @@ subroutine grid_damage_spectral_init()
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! set default and user defined options for PETSc
|
! set default and user defined options for PETSc
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-damage_snes_type newtonls -damage_snes_mf &
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-damage_snes_type newtonls -damage_snes_mf &
|
||||||
&-damage_snes_ksp_ew -damage_ksp_type fgmres',ierr)
|
&-damage_snes_ksp_ew -damage_ksp_type fgmres',err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
|
||||||
! initialize solver specific parts of PETSc
|
|
||||||
call SNESCreate(PETSC_COMM_WORLD,damage_snes,ierr); CHKERRQ(ierr)
|
|
||||||
call SNESSetOptionsPrefix(damage_snes,'damage_',ierr);CHKERRQ(ierr)
|
|
||||||
localK = 0
|
|
||||||
localK(worldrank) = grid3
|
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,ierr)
|
|
||||||
call DMDACreate3D(PETSC_COMM_WORLD, &
|
|
||||||
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
|
||||||
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
|
||||||
grid(1),grid(2),grid(3), & ! global grid
|
|
||||||
1, 1, worldsize, &
|
|
||||||
1, 0, & ! #dof (damage phase field), ghost boundary width (domain overlap)
|
|
||||||
[grid(1)],[grid(2)],localK, & ! local grid
|
|
||||||
damage_grid,ierr) ! handle, error
|
|
||||||
CHKERRQ(ierr)
|
|
||||||
call SNESSetDM(damage_snes,damage_grid,ierr); CHKERRQ(ierr) ! connect snes to da
|
|
||||||
call DMsetFromOptions(damage_grid,ierr); CHKERRQ(ierr)
|
|
||||||
call DMsetUp(damage_grid,ierr); CHKERRQ(ierr)
|
|
||||||
call DMCreateGlobalVector(damage_grid,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 1, i.e. every def grad tensor)
|
|
||||||
call DMDASNESSetFunctionLocal(damage_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector
|
|
||||||
CHKERRQ(ierr)
|
|
||||||
call SNESSetFromOptions(damage_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments
|
|
||||||
call SNESGetType(damage_snes,snes_type,ierr); CHKERRQ(ierr)
|
|
||||||
if (trim(snes_type) == 'vinewtonrsls' .or. &
|
|
||||||
trim(snes_type) == 'vinewtonssls') then
|
|
||||||
call DMGetGlobalVector(damage_grid,lBound,ierr); CHKERRQ(ierr)
|
|
||||||
call DMGetGlobalVector(damage_grid,uBound,ierr); CHKERRQ(ierr)
|
|
||||||
call VecSet(lBound,0.0_pReal,ierr); CHKERRQ(ierr)
|
|
||||||
call VecSet(uBound,1.0_pReal,ierr); CHKERRQ(ierr)
|
|
||||||
call SNESVISetVariableBounds(damage_snes,lBound,uBound,ierr) ! variable bounds for variational inequalities like contact mechanics, damage etc.
|
|
||||||
call DMRestoreGlobalVector(damage_grid,lBound,ierr); CHKERRQ(ierr)
|
|
||||||
call DMRestoreGlobalVector(damage_grid,uBound,ierr); CHKERRQ(ierr)
|
|
||||||
end if
|
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! init fields
|
! init fields
|
||||||
call DMDAGetCorners(damage_grid,xstart,ystart,zstart,xend,yend,zend,ierr)
|
|
||||||
CHKERRQ(ierr)
|
|
||||||
xend = xstart + xend - 1
|
|
||||||
yend = ystart + yend - 1
|
|
||||||
zend = zstart + zend - 1
|
|
||||||
allocate(phi_current(grid(1),grid(2),grid3), source=1.0_pReal)
|
allocate(phi_current(grid(1),grid(2),grid3), source=1.0_pReal)
|
||||||
allocate(phi_lastInc(grid(1),grid(2),grid3), source=1.0_pReal)
|
allocate(phi_lastInc(grid(1),grid(2),grid3), source=1.0_pReal)
|
||||||
allocate(phi_stagInc(grid(1),grid(2),grid3), source=1.0_pReal)
|
allocate(phi_stagInc(grid(1),grid(2),grid3), source=1.0_pReal)
|
||||||
|
|
||||||
call VecSet(solution_vec,1.0_pReal,ierr); CHKERRQ(ierr)
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
! initialize solver specific parts of PETSc
|
||||||
|
call SNESCreate(PETSC_COMM_WORLD,SNES_damage,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetOptionsPrefix(SNES_damage,'damage_',err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
localK = 0_pPetscInt
|
||||||
|
localK(worldrank) = int(grid3,pPetscInt)
|
||||||
|
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
call DMDACreate3D(PETSC_COMM_WORLD, &
|
||||||
|
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
||||||
|
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
||||||
|
int(grid(1),pPetscInt),int(grid(2),pPetscInt),int(grid(3),pPetscInt), & ! global grid
|
||||||
|
1_pPetscInt, 1_pPetscInt, int(worldsize,pPetscInt), &
|
||||||
|
1_pPetscInt, 0_pPetscInt, & ! #dof (phi, scalar), ghost boundary width (domain overlap)
|
||||||
|
[int(grid(1),pPetscInt)],[int(grid(2),pPetscInt)],localK, & ! local grid
|
||||||
|
damage_grid,err_PETSc) ! handle, error
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMsetFromOptions(damage_grid,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMsetUp(damage_grid,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMCreateGlobalVector(damage_grid,solution_vec,err_PETSc) ! global solution vector (grid x 1, i.e. every def grad tensor)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMDASNESSetFunctionLocal(damage_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,err_PETSc) ! residual vector of same shape as solution vector
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetDM(SNES_damage,damage_grid,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetFromOptions(SNES_damage,err_PETSc) ! pull it all together with additional CLI arguments
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESGetType(SNES_damage,snes_type,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
if (trim(snes_type) == 'vinewtonrsls' .or. &
|
||||||
|
trim(snes_type) == 'vinewtonssls') then
|
||||||
|
call DMGetGlobalVector(damage_grid,lBound,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMGetGlobalVector(damage_grid,uBound,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call VecSet(lBound,0.0_pReal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call VecSet(uBound,1.0_pReal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESVISetVariableBounds(SNES_damage,lBound,uBound,err_PETSc) ! variable bounds for variational inequalities
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMRestoreGlobalVector(damage_grid,lBound,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMRestoreGlobalVector(damage_grid,uBound,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
end if
|
||||||
|
call VecSet(solution_vec,1.0_pReal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
call updateReference
|
call updateReference()
|
||||||
|
|
||||||
end subroutine grid_damage_spectral_init
|
end subroutine grid_damage_spectral_init
|
||||||
|
|
||||||
|
@ -169,7 +180,8 @@ function grid_damage_spectral_solution(Delta_t) result(solution)
|
||||||
PetscInt :: devNull
|
PetscInt :: devNull
|
||||||
PetscReal :: phi_min, phi_max, stagNorm
|
PetscReal :: phi_min, phi_max, stagNorm
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
PetscErrorCode :: err_PETSc
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
|
|
||||||
solution%converged =.false.
|
solution%converged =.false.
|
||||||
|
@ -178,8 +190,10 @@ function grid_damage_spectral_solution(Delta_t) result(solution)
|
||||||
! set module wide availabe data
|
! set module wide availabe data
|
||||||
params%Delta_t = Delta_t
|
params%Delta_t = Delta_t
|
||||||
|
|
||||||
call SNESSolve(damage_snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr)
|
call SNESSolve(SNES_damage,PETSC_NULL_VEC,solution_vec,err_PETSc)
|
||||||
call SNESGetConvergedReason(damage_snes,reason,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESGetConvergedReason(SNES_damage,reason,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
if (reason < 1) then
|
if (reason < 1) then
|
||||||
solution%converged = .false.
|
solution%converged = .false.
|
||||||
|
@ -189,9 +203,11 @@ function grid_damage_spectral_solution(Delta_t) result(solution)
|
||||||
solution%iterationsNeeded = totalIter
|
solution%iterationsNeeded = totalIter
|
||||||
end if
|
end if
|
||||||
stagNorm = maxval(abs(phi_current - phi_stagInc))
|
stagNorm = maxval(abs(phi_current - phi_stagInc))
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,stagNorm,1,MPI_DOUBLE,MPI_MAX,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,stagNorm,1_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_MAX,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
solution%stagConverged = stagNorm < max(num%eps_damage_atol, num%eps_damage_rtol*maxval(phi_current))
|
solution%stagConverged = stagNorm < max(num%eps_damage_atol, num%eps_damage_rtol*maxval(phi_current))
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,solution%stagConverged,1,MPI_LOGICAL,MPI_LAND,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,solution%stagConverged,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LAND,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
phi_stagInc = phi_current
|
phi_stagInc = phi_current
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -202,8 +218,10 @@ function grid_damage_spectral_solution(Delta_t) result(solution)
|
||||||
call homogenization_set_phi(phi_current(i,j,k),ce)
|
call homogenization_set_phi(phi_current(i,j,k),ce)
|
||||||
end do; end do; end do
|
end do; end do; end do
|
||||||
|
|
||||||
call VecMin(solution_vec,devNull,phi_min,ierr); CHKERRQ(ierr)
|
call VecMin(solution_vec,devNull,phi_min,err_PETSc)
|
||||||
call VecMax(solution_vec,devNull,phi_max,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call VecMax(solution_vec,devNull,phi_max,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
if (solution%converged) &
|
if (solution%converged) &
|
||||||
print'(/,1x,a)', '... nonlocal damage converged .....................................'
|
print'(/,1x,a)', '... nonlocal damage converged .....................................'
|
||||||
print'(/,1x,a,f8.6,2x,f8.6,2x,e11.4)', 'Minimum|Maximum|Delta Damage = ', phi_min, phi_max, stagNorm
|
print'(/,1x,a,f8.6,2x,f8.6,2x,e11.4)', 'Minimum|Maximum|Delta Damage = ', phi_min, phi_max, stagNorm
|
||||||
|
@ -221,18 +239,21 @@ subroutine grid_damage_spectral_forward(cutBack)
|
||||||
logical, intent(in) :: cutBack
|
logical, intent(in) :: cutBack
|
||||||
integer :: i, j, k, ce
|
integer :: i, j, k, ce
|
||||||
DM :: dm_local
|
DM :: dm_local
|
||||||
PetscScalar, dimension(:,:,:), pointer :: x_scal
|
PetscScalar, dimension(:,:,:), pointer :: phi_PETSc
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
if (cutBack) then
|
if (cutBack) then
|
||||||
phi_current = phi_lastInc
|
phi_current = phi_lastInc
|
||||||
phi_stagInc = phi_lastInc
|
phi_stagInc = phi_lastInc
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! reverting damage field state
|
! reverting damage field state
|
||||||
call SNESGetDM(damage_snes,dm_local,ierr); CHKERRQ(ierr)
|
call SNESGetDM(SNES_damage,dm_local,err_PETSc)
|
||||||
call DMDAVecGetArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with
|
CHKERRQ(err_PETSc)
|
||||||
x_scal(xstart:xend,ystart:yend,zstart:zend) = phi_current
|
call DMDAVecGetArrayF90(dm_local,solution_vec,phi_PETSc,err_PETSc) !< get the data out of PETSc to work with
|
||||||
call DMDAVecRestoreArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
phi_PETSc = phi_current
|
||||||
|
call DMDAVecRestoreArrayF90(dm_local,solution_vec,phi_PETSc,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
ce = 0
|
ce = 0
|
||||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||||
ce = ce + 1
|
ce = ce + 1
|
||||||
|
@ -249,7 +270,7 @@ end subroutine grid_damage_spectral_forward
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief forms the spectral damage residual vector
|
!> @brief forms the spectral damage residual vector
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
subroutine formResidual(in,x_scal,r,dummy,err_PETSc)
|
||||||
|
|
||||||
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
|
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
|
||||||
in
|
in
|
||||||
|
@ -258,9 +279,9 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
||||||
x_scal
|
x_scal
|
||||||
PetscScalar, dimension( &
|
PetscScalar, dimension( &
|
||||||
X_RANGE,Y_RANGE,Z_RANGE), intent(out) :: &
|
X_RANGE,Y_RANGE,Z_RANGE), intent(out) :: &
|
||||||
f_scal
|
r
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer :: i, j, k, ce
|
integer :: i, j, k, ce
|
||||||
|
|
||||||
|
|
||||||
|
@ -301,7 +322,8 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! constructing residual
|
! constructing residual
|
||||||
f_scal = scalarField_real(1:grid(1),1:grid(2),1:grid3) - phi_current
|
r = scalarField_real(1:grid(1),1:grid(2),1:grid3) - phi_current
|
||||||
|
err_PETSc = 0
|
||||||
|
|
||||||
end subroutine formResidual
|
end subroutine formResidual
|
||||||
|
|
||||||
|
@ -311,7 +333,8 @@ end subroutine formResidual
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine updateReference()
|
subroutine updateReference()
|
||||||
|
|
||||||
integer :: ce,ierr
|
integer :: ce
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
|
|
||||||
K_ref = 0.0_pReal
|
K_ref = 0.0_pReal
|
||||||
|
@ -322,9 +345,11 @@ subroutine updateReference()
|
||||||
end do
|
end do
|
||||||
|
|
||||||
K_ref = K_ref*wgt
|
K_ref = K_ref*wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
mu_ref = mu_ref*wgt
|
mu_ref = mu_ref*wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,mu_ref,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,mu_ref,1_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
end subroutine updateReference
|
end subroutine updateReference
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ module grid_mechanical_FEM
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc data
|
! PETSc data
|
||||||
DM :: mechanical_grid
|
DM :: mechanical_grid
|
||||||
SNES :: mechanical_snes
|
SNES :: SNES_mechanical
|
||||||
Vec :: solution_current, solution_lastInc, solution_rate
|
Vec :: solution_current, solution_lastInc, solution_rate
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -60,7 +60,6 @@ module grid_mechanical_FEM
|
||||||
real(pReal), dimension(3) :: delta
|
real(pReal), dimension(3) :: delta
|
||||||
real(pReal), dimension(3,8) :: BMat
|
real(pReal), dimension(3,8) :: BMat
|
||||||
real(pReal), dimension(8,8) :: HGMat
|
real(pReal), dimension(8,8) :: HGMat
|
||||||
PetscInt :: xstart,ystart,zstart,xend,yend,zend
|
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! stress, stiffness and compliance average etc.
|
! stress, stiffness and compliance average etc.
|
||||||
|
@ -107,7 +106,8 @@ subroutine grid_mechanical_FEM_init
|
||||||
1.0_pReal,-1.0_pReal,-1.0_pReal,-1.0_pReal, &
|
1.0_pReal,-1.0_pReal,-1.0_pReal,-1.0_pReal, &
|
||||||
1.0_pReal, 1.0_pReal, 1.0_pReal, 1.0_pReal], [4,8])
|
1.0_pReal, 1.0_pReal, 1.0_pReal, 1.0_pReal], [4,8])
|
||||||
real(pReal), dimension(3,3,3,3) :: devNull
|
real(pReal), dimension(3,3,3,3) :: devNull
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
||||||
u_current,u_lastInc
|
u_current,u_lastInc
|
||||||
PetscInt, dimension(0:worldsize-1) :: localK
|
PetscInt, dimension(0:worldsize-1) :: localK
|
||||||
|
@ -145,12 +145,11 @@ subroutine grid_mechanical_FEM_init
|
||||||
! set default and user defined options for PETSc
|
! set default and user defined options for PETSc
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS, &
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS, &
|
||||||
'-mechanical_snes_type newtonls -mechanical_ksp_type fgmres &
|
'-mechanical_snes_type newtonls -mechanical_ksp_type fgmres &
|
||||||
&-mechanical_ksp_max_it 25 -mechanical_pc_type ml &
|
&-mechanical_ksp_max_it 25', &
|
||||||
&-mechanical_mg_levels_ksp_type chebyshev', &
|
err_PETSc)
|
||||||
ierr)
|
CHKERRQ(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
CHKERRQ(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! allocate global fields
|
! allocate global fields
|
||||||
|
@ -160,62 +159,61 @@ subroutine grid_mechanical_FEM_init
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! initialize solver specific parts of PETSc
|
! initialize solver specific parts of PETSc
|
||||||
call SNESCreate(PETSC_COMM_WORLD,mechanical_snes,ierr)
|
call SNESCreate(PETSC_COMM_WORLD,SNES_mechanical,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetOptionsPrefix(mechanical_snes,'mechanical_',ierr)
|
call SNESSetOptionsPrefix(SNES_mechanical,'mechanical_',err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
localK = 0
|
localK = 0_pPetscInt
|
||||||
localK(worldrank) = grid3
|
localK(worldrank) = int(grid3,pPetscInt)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call DMDACreate3d(PETSC_COMM_WORLD, &
|
call DMDACreate3d(PETSC_COMM_WORLD, &
|
||||||
DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC, &
|
DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC, &
|
||||||
DMDA_STENCIL_BOX, &
|
DMDA_STENCIL_BOX, &
|
||||||
grid(1),grid(2),grid(3), &
|
int(grid(1),pPetscInt),int(grid(2),pPetscInt),int(grid(3),pPetscInt), & ! global grid
|
||||||
1, 1, worldsize, &
|
1_pPetscInt, 1_pPetscInt, int(worldsize,pPetscInt), &
|
||||||
3, 1, &
|
3_pPetscInt, 1_pPetscInt, & ! #dof (u, vector), ghost boundary width (domain overlap)
|
||||||
[grid(1)],[grid(2)],localK, &
|
[int(grid(1),pPetscInt)],[int(grid(2),pPetscInt)],localK, & ! local grid
|
||||||
mechanical_grid,ierr)
|
mechanical_grid,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetDM(mechanical_snes,mechanical_grid,ierr)
|
call DMsetFromOptions(mechanical_grid,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMsetFromOptions(mechanical_grid,ierr)
|
call DMsetUp(mechanical_grid,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMsetUp(mechanical_grid,ierr)
|
call DMDASetUniformCoordinates(mechanical_grid,0.0_pReal,geomSize(1),0.0_pReal,geomSize(2),0.0_pReal,geomSize(3),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDASetUniformCoordinates(mechanical_grid,0.0_pReal,geomSize(1),0.0_pReal,geomSize(2),0.0_pReal,geomSize(3),ierr)
|
call DMCreateGlobalVector(mechanical_grid,solution_current,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMCreateGlobalVector(mechanical_grid,solution_current,ierr)
|
call DMCreateGlobalVector(mechanical_grid,solution_lastInc,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMCreateGlobalVector(mechanical_grid,solution_lastInc,ierr)
|
call DMCreateGlobalVector(mechanical_grid,solution_rate ,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMCreateGlobalVector(mechanical_grid,solution_rate ,ierr)
|
call DMSNESSetFunctionLocal(mechanical_grid,formResidual,PETSC_NULL_SNES,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMSNESSetFunctionLocal(mechanical_grid,formResidual,PETSC_NULL_SNES,ierr)
|
call DMSNESSetJacobianLocal(mechanical_grid,formJacobian,PETSC_NULL_SNES,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMSNESSetJacobianLocal(mechanical_grid,formJacobian,PETSC_NULL_SNES,ierr)
|
call SNESSetConvergenceTest(SNES_mechanical,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,err_PETSc) ! specify custom convergence check function "_converged"
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetConvergenceTest(mechanical_snes,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,ierr) ! specify custom convergence check function "_converged"
|
call SNESSetMaxLinearSolveFailures(SNES_mechanical, huge(1_pPetscInt), err_PETSc) ! ignore linear solve failures
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetMaxLinearSolveFailures(mechanical_snes, huge(1), ierr) ! ignore linear solve failures
|
call SNESSetDM(SNES_mechanical,mechanical_grid,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetFromOptions(mechanical_snes,ierr) ! pull it all together with additional cli arguments
|
call SNESSetFromOptions(SNES_mechanical,err_PETSc) ! pull it all together with additional cli arguments
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! init fields
|
! init fields
|
||||||
call VecSet(solution_current,0.0_pReal,ierr);CHKERRQ(ierr)
|
call VecSet(solution_current,0.0_pReal,err_PETSc)
|
||||||
call VecSet(solution_lastInc,0.0_pReal,ierr);CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call VecSet(solution_rate ,0.0_pReal,ierr);CHKERRQ(ierr)
|
call VecSet(solution_lastInc,0.0_pReal,err_PETSc)
|
||||||
call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,ierr)
|
CHKERRQ(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
call VecSet(solution_rate ,0.0_pReal,err_PETSc)
|
||||||
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
CHKERRQ(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
call DMDAGetCorners(mechanical_grid,xstart,ystart,zstart,xend,yend,zend,ierr) ! local grid extent
|
|
||||||
CHKERRQ(ierr)
|
|
||||||
xend = xstart+xend-1
|
|
||||||
yend = ystart+yend-1
|
|
||||||
zend = zstart+zend-1
|
|
||||||
delta = geomSize/real(grid,pReal) ! grid spacing
|
delta = geomSize/real(grid,pReal) ! grid spacing
|
||||||
detJ = product(delta) ! cell volume
|
detJ = product(delta) ! cell volume
|
||||||
|
|
||||||
|
@ -240,17 +238,17 @@ subroutine grid_mechanical_FEM_init
|
||||||
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
||||||
|
|
||||||
call HDF5_read(P_aim,groupHandle,'P_aim',.false.)
|
call HDF5_read(P_aim,groupHandle,'P_aim',.false.)
|
||||||
call MPI_Bcast(P_aim,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(P_aim,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if(ierr /=0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aim,groupHandle,'F_aim',.false.)
|
call HDF5_read(F_aim,groupHandle,'F_aim',.false.)
|
||||||
call MPI_Bcast(F_aim,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aim,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if(ierr /=0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aim_lastInc,groupHandle,'F_aim_lastInc',.false.)
|
call HDF5_read(F_aim_lastInc,groupHandle,'F_aim_lastInc',.false.)
|
||||||
call MPI_Bcast(F_aim_lastInc,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aim_lastInc,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if(ierr /=0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aimDot,groupHandle,'F_aimDot',.false.)
|
call HDF5_read(F_aimDot,groupHandle,'F_aimDot',.false.)
|
||||||
call MPI_Bcast(F_aimDot,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aimDot,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if(ierr /=0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F,groupHandle,'F')
|
call HDF5_read(F,groupHandle,'F')
|
||||||
call HDF5_read(F_lastInc,groupHandle,'F_lastInc')
|
call HDF5_read(F_lastInc,groupHandle,'F_lastInc')
|
||||||
call HDF5_read(u_current,groupHandle,'u')
|
call HDF5_read(u_current,groupHandle,'u')
|
||||||
|
@ -266,19 +264,19 @@ subroutine grid_mechanical_FEM_init
|
||||||
call utilities_constitutiveResponse(P_current,P_av,C_volAvg,devNull, & ! stress field, stress avg, global average of stiffness and (min+max)/2
|
call utilities_constitutiveResponse(P_current,P_av,C_volAvg,devNull, & ! stress field, stress avg, global average of stiffness and (min+max)/2
|
||||||
F, & ! target F
|
F, & ! target F
|
||||||
0.0_pReal) ! time increment
|
0.0_pReal) ! time increment
|
||||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,ierr)
|
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
restartRead2: if (interface_restartInc > 0) then
|
restartRead2: if (interface_restartInc > 0) then
|
||||||
print'(1x,a,i0,a)', 'reading more restart data of increment ', interface_restartInc, ' from file'
|
print'(1x,a,i0,a)', 'reading more restart data of increment ', interface_restartInc, ' from file'
|
||||||
call HDF5_read(C_volAvg,groupHandle,'C_volAvg',.false.)
|
call HDF5_read(C_volAvg,groupHandle,'C_volAvg',.false.)
|
||||||
call MPI_Bcast(C_volAvg,81,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(C_volAvg,81_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if(ierr /=0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(C_volAvgLastInc,groupHandle,'C_volAvgLastInc',.false.)
|
call HDF5_read(C_volAvgLastInc,groupHandle,'C_volAvgLastInc',.false.)
|
||||||
call MPI_Bcast(C_volAvgLastInc,81,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(C_volAvgLastInc,81_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if(ierr /=0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
call HDF5_closeGroup(groupHandle)
|
call HDF5_closeGroup(groupHandle)
|
||||||
call HDF5_closeFile(fileHandle)
|
call HDF5_closeFile(fileHandle)
|
||||||
|
@ -301,7 +299,7 @@ function grid_mechanical_FEM_solution(incInfoIn) result(solution)
|
||||||
solution
|
solution
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc Data
|
! PETSc Data
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
|
|
||||||
incInfo = incInfoIn
|
incInfo = incInfoIn
|
||||||
|
@ -310,15 +308,10 @@ function grid_mechanical_FEM_solution(incInfoIn) result(solution)
|
||||||
! update stiffness (and gamma operator)
|
! update stiffness (and gamma operator)
|
||||||
S = utilities_maskedCompliance(params%rotation_BC,params%stress_mask,C_volAvg)
|
S = utilities_maskedCompliance(params%rotation_BC,params%stress_mask,C_volAvg)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
call SNESsolve(SNES_mechanical,PETSC_NULL_VEC,solution_current,err_PETSc)
|
||||||
! solve BVP
|
CHKERRQ(err_PETSc)
|
||||||
call SNESsolve(mechanical_snes,PETSC_NULL_VEC,solution_current,ierr)
|
call SNESGetConvergedReason(SNES_mechanical,reason,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
|
||||||
! check convergence
|
|
||||||
call SNESGetConvergedReason(mechanical_snes,reason,ierr)
|
|
||||||
CHKERRQ(ierr)
|
|
||||||
|
|
||||||
solution%converged = reason > 0
|
solution%converged = reason > 0
|
||||||
solution%iterationsNeeded = totalIter
|
solution%iterationsNeeded = totalIter
|
||||||
|
@ -348,15 +341,15 @@ subroutine grid_mechanical_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remai
|
||||||
deformation_BC
|
deformation_BC
|
||||||
type(rotation), intent(in) :: &
|
type(rotation), intent(in) :: &
|
||||||
rotation_BC
|
rotation_BC
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
||||||
u_current,u_lastInc
|
u_current,u_lastInc
|
||||||
|
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,ierr)
|
call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
if (cutBack) then
|
if (cutBack) then
|
||||||
C_volAvg = C_volAvgLastInc
|
C_volAvg = C_volAvgLastInc
|
||||||
|
@ -380,13 +373,16 @@ subroutine grid_mechanical_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remai
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if (guess) then
|
if (guess) then
|
||||||
call VecWAXPY(solution_rate,-1.0_pReal,solution_lastInc,solution_current,ierr)
|
call VecWAXPY(solution_rate,-1.0_pReal,solution_lastInc,solution_current,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call VecScale(solution_rate,1.0_pReal/Delta_t_old,ierr); CHKERRQ(ierr)
|
call VecScale(solution_rate,1.0_pReal/Delta_t_old,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
else
|
else
|
||||||
call VecSet(solution_rate,0.0_pReal,ierr); CHKERRQ(ierr)
|
call VecSet(solution_rate,0.0_pReal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
endif
|
endif
|
||||||
call VecCopy(solution_current,solution_lastInc,ierr); CHKERRQ(ierr)
|
call VecCopy(solution_current,solution_lastInc,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
F_lastInc = F
|
F_lastInc = F
|
||||||
|
|
||||||
|
@ -401,12 +397,12 @@ subroutine grid_mechanical_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remai
|
||||||
if (stress_BC%myType=='dot_P') P_aim = P_aim &
|
if (stress_BC%myType=='dot_P') P_aim = P_aim &
|
||||||
+ merge(.0_pReal,stress_BC%values,stress_BC%mask)*Delta_t
|
+ merge(.0_pReal,stress_BC%values,stress_BC%mask)*Delta_t
|
||||||
|
|
||||||
call VecAXPY(solution_current,Delta_t,solution_rate,ierr); CHKERRQ(ierr)
|
call VecAXPY(solution_current,Delta_t,solution_rate,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,ierr)
|
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! set module wide available data
|
! set module wide available data
|
||||||
|
@ -432,15 +428,15 @@ end subroutine grid_mechanical_FEM_updateCoords
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine grid_mechanical_FEM_restartWrite
|
subroutine grid_mechanical_FEM_restartWrite
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer(HID_T) :: fileHandle, groupHandle
|
integer(HID_T) :: fileHandle, groupHandle
|
||||||
PetscScalar, dimension(:,:,:,:), pointer :: u_current,u_lastInc
|
PetscScalar, dimension(:,:,:,:), pointer :: u_current,u_lastInc
|
||||||
|
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,ierr)
|
call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
print'(1x,a)', 'writing solver data required for restart to file'; flush(IO_STDOUT)
|
print'(1x,a)', 'writing solver data required for restart to file'; flush(IO_STDOUT)
|
||||||
|
|
||||||
|
@ -466,10 +462,10 @@ subroutine grid_mechanical_FEM_restartWrite
|
||||||
call HDF5_closeFile(fileHandle)
|
call HDF5_closeFile(fileHandle)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,ierr)
|
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine grid_mechanical_FEM_restartWrite
|
end subroutine grid_mechanical_FEM_restartWrite
|
||||||
|
|
||||||
|
@ -477,7 +473,7 @@ end subroutine grid_mechanical_FEM_restartWrite
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief convergence check
|
!> @brief convergence check
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine converged(snes_local,PETScIter,devNull1,devNull2,fnorm,reason,dummy,ierr)
|
subroutine converged(snes_local,PETScIter,devNull1,devNull2,fnorm,reason,dummy,err_PETSc)
|
||||||
|
|
||||||
SNES :: snes_local
|
SNES :: snes_local
|
||||||
PetscInt, intent(in) :: PETScIter
|
PetscInt, intent(in) :: PETScIter
|
||||||
|
@ -487,7 +483,7 @@ subroutine converged(snes_local,PETScIter,devNull1,devNull2,fnorm,reason,dummy,i
|
||||||
fnorm
|
fnorm
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
real(pReal) :: &
|
real(pReal) :: &
|
||||||
err_div, &
|
err_div, &
|
||||||
divTol, &
|
divTol, &
|
||||||
|
@ -513,6 +509,7 @@ subroutine converged(snes_local,PETScIter,devNull1,devNull2,fnorm,reason,dummy,i
|
||||||
err_BC/BCTol, ' (',err_BC, ' Pa, tol = ',BCTol,')'
|
err_BC/BCTol, ' (',err_BC, ' Pa, tol = ',BCTol,')'
|
||||||
print'(/,1x,a)', '==========================================================================='
|
print'(/,1x,a)', '==========================================================================='
|
||||||
flush(IO_STDOUT)
|
flush(IO_STDOUT)
|
||||||
|
err_PETSc = 0
|
||||||
|
|
||||||
end subroutine converged
|
end subroutine converged
|
||||||
|
|
||||||
|
@ -521,24 +518,25 @@ end subroutine converged
|
||||||
!> @brief forms the residual vector
|
!> @brief forms the residual vector
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine formResidual(da_local,x_local, &
|
subroutine formResidual(da_local,x_local, &
|
||||||
f_local,dummy,ierr)
|
f_local,dummy,err_PETSc)
|
||||||
|
|
||||||
DM :: da_local
|
DM :: da_local
|
||||||
Vec :: x_local, f_local
|
Vec :: x_local, f_local
|
||||||
PetscScalar, pointer,dimension(:,:,:,:) :: x_scal, f_scal
|
PetscScalar, pointer,dimension(:,:,:,:) :: x_scal, r
|
||||||
PetscScalar, dimension(8,3) :: x_elem, f_elem
|
PetscScalar, dimension(8,3) :: x_elem, f_elem
|
||||||
PetscInt :: i, ii, j, jj, k, kk, ctr, ele
|
PetscInt :: i, ii, j, jj, k, kk, ctr, ele
|
||||||
PetscInt :: &
|
PetscInt :: &
|
||||||
PETScIter, &
|
PETScIter, &
|
||||||
nfuncs
|
nfuncs
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
real(pReal), dimension(3,3,3,3) :: devNull
|
real(pReal), dimension(3,3,3,3) :: devNull
|
||||||
|
|
||||||
call SNESGetNumberFunctionEvals(mechanical_snes,nfuncs,ierr)
|
call SNESGetNumberFunctionEvals(SNES_mechanical,nfuncs,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESGetIterationNumber(mechanical_snes,PETScIter,ierr)
|
call SNESGetIterationNumber(SNES_mechanical,PETScIter,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment
|
if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment
|
||||||
|
|
||||||
|
@ -556,24 +554,26 @@ subroutine formResidual(da_local,x_local, &
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! get deformation gradient
|
! get deformation gradient
|
||||||
call DMDAVecGetArrayF90(da_local,x_local,x_scal,ierr);CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da_local,x_local,x_scal,err_PETSc)
|
||||||
do k = zstart, zend; do j = ystart, yend; do i = xstart, xend
|
CHKERRQ(err_PETSc)
|
||||||
|
do k = grid3offset+1, grid3offset+grid3; do j = 1, grid(2); do i = 1, grid(1)
|
||||||
ctr = 0
|
ctr = 0
|
||||||
do kk = 0, 1; do jj = 0, 1; do ii = 0, 1
|
do kk = -1, 0; do jj = -1, 0; do ii = -1, 0
|
||||||
ctr = ctr + 1
|
ctr = ctr + 1
|
||||||
x_elem(ctr,1:3) = x_scal(0:2,i+ii,j+jj,k+kk)
|
x_elem(ctr,1:3) = x_scal(0:2,i+ii,j+jj,k+kk)
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
ii = i-xstart+1; jj = j-ystart+1; kk = k-zstart+1
|
F(1:3,1:3,i,j,k-grid3offset) = params%rotation_BC%rotate(F_aim,active=.true.) + transpose(matmul(BMat,x_elem))
|
||||||
F(1:3,1:3,ii,jj,kk) = params%rotation_BC%rotate(F_aim,active=.true.) + transpose(matmul(BMat,x_elem))
|
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
call DMDAVecRestoreArrayF90(da_local,x_local,x_scal,ierr);CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da_local,x_local,x_scal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! evaluate constitutive response
|
! evaluate constitutive response
|
||||||
call utilities_constitutiveResponse(P_current,&
|
call utilities_constitutiveResponse(P_current,&
|
||||||
P_av,C_volAvg,devNull, &
|
P_av,C_volAvg,devNull, &
|
||||||
F,params%Delta_t,params%rotation_BC)
|
F,params%Delta_t,params%rotation_BC)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! stress BC handling
|
! stress BC handling
|
||||||
|
@ -582,47 +582,53 @@ subroutine formResidual(da_local,x_local, &
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! constructing residual
|
! constructing residual
|
||||||
call VecSet(f_local,0.0_pReal,ierr);CHKERRQ(ierr)
|
call VecSet(f_local,0.0_pReal,err_PETSc)
|
||||||
call DMDAVecGetArrayF90(da_local,f_local,f_scal,ierr);CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecGetArrayF90(da_local,x_local,x_scal,ierr);CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da_local,f_local,r,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMDAVecGetArrayF90(da_local,x_local,x_scal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
ele = 0
|
ele = 0
|
||||||
do k = zstart, zend; do j = ystart, yend; do i = xstart, xend
|
do k = grid3offset+1, grid3offset+grid3; do j = 1, grid(2); do i = 1, grid(1)
|
||||||
ctr = 0
|
ctr = 0
|
||||||
do kk = 0, 1; do jj = 0, 1; do ii = 0, 1
|
do kk = -1, 0; do jj = -1, 0; do ii = -1, 0
|
||||||
ctr = ctr + 1
|
ctr = ctr + 1
|
||||||
x_elem(ctr,1:3) = x_scal(0:2,i+ii,j+jj,k+kk)
|
x_elem(ctr,1:3) = x_scal(0:2,i+ii,j+jj,k+kk)
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
ii = i-xstart+1; jj = j-ystart+1; kk = k-zstart+1
|
|
||||||
ele = ele + 1
|
ele = ele + 1
|
||||||
f_elem = matmul(transpose(BMat),transpose(P_current(1:3,1:3,ii,jj,kk)))*detJ + &
|
f_elem = matmul(transpose(BMat),transpose(P_current(1:3,1:3,i,j,k-grid3offset)))*detJ + &
|
||||||
matmul(HGMat,x_elem)*(homogenization_dPdF(1,1,1,1,ele) + &
|
matmul(HGMat,x_elem)*(homogenization_dPdF(1,1,1,1,ele) + &
|
||||||
homogenization_dPdF(2,2,2,2,ele) + &
|
homogenization_dPdF(2,2,2,2,ele) + &
|
||||||
homogenization_dPdF(3,3,3,3,ele))/3.0_pReal
|
homogenization_dPdF(3,3,3,3,ele))/3.0_pReal
|
||||||
ctr = 0
|
ctr = 0
|
||||||
do kk = 0, 1; do jj = 0, 1; do ii = 0, 1
|
do kk = -1, 0; do jj = -1, 0; do ii = -1, 0
|
||||||
ctr = ctr + 1
|
ctr = ctr + 1
|
||||||
f_scal(0:2,i+ii,j+jj,k+kk) = f_scal(0:2,i+ii,j+jj,k+kk) + f_elem(ctr,1:3)
|
r(0:2,i+ii,j+jj,k+kk) = r(0:2,i+ii,j+jj,k+kk) + f_elem(ctr,1:3)
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
call DMDAVecRestoreArrayF90(da_local,x_local,x_scal,ierr);CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da_local,x_local,x_scal,err_PETSc)
|
||||||
call DMDAVecRestoreArrayF90(da_local,f_local,f_scal,ierr);CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMDAVecRestoreArrayF90(da_local,f_local,r,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! applying boundary conditions
|
! applying boundary conditions
|
||||||
call DMDAVecGetArrayF90(da_local,f_local,f_scal,ierr);CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da_local,f_local,r,err_PETSc)
|
||||||
if (zstart == 0) then
|
CHKERRQ(err_PETSc)
|
||||||
f_scal(0:2,xstart,ystart,zstart) = 0.0
|
if (grid3offset == 0) then
|
||||||
f_scal(0:2,xend+1,ystart,zstart) = 0.0
|
r(0:2,0, 0, 0) = 0.0_pReal
|
||||||
f_scal(0:2,xstart,yend+1,zstart) = 0.0
|
r(0:2,grid(1),0, 0) = 0.0_pReal
|
||||||
f_scal(0:2,xend+1,yend+1,zstart) = 0.0
|
r(0:2,0, grid(2),0) = 0.0_pReal
|
||||||
|
r(0:2,grid(1),grid(2),0) = 0.0_pReal
|
||||||
end if
|
end if
|
||||||
if (zend + 1 == grid(3)) then
|
if (grid3+grid3offset == grid(3)) then
|
||||||
f_scal(0:2,xstart,ystart,zend+1) = 0.0
|
r(0:2,0, 0, grid(3)) = 0.0_pReal
|
||||||
f_scal(0:2,xend+1,ystart,zend+1) = 0.0
|
r(0:2,grid(1),0, grid(3)) = 0.0_pReal
|
||||||
f_scal(0:2,xstart,yend+1,zend+1) = 0.0
|
r(0:2,0, grid(2),grid(3)) = 0.0_pReal
|
||||||
f_scal(0:2,xend+1,yend+1,zend+1) = 0.0
|
r(0:2,grid(1),grid(2),grid(3)) = 0.0_pReal
|
||||||
end if
|
end if
|
||||||
call DMDAVecRestoreArrayF90(da_local,f_local,f_scal,ierr);CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da_local,f_local,r,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine formResidual
|
end subroutine formResidual
|
||||||
|
|
||||||
|
@ -630,7 +636,7 @@ end subroutine formResidual
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief forms the FEM stiffness matrix
|
!> @brief forms the FEM stiffness matrix
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine formJacobian(da_local,x_local,Jac_pre,Jac,dummy,ierr)
|
subroutine formJacobian(da_local,x_local,Jac_pre,Jac,dummy,err_PETSc)
|
||||||
|
|
||||||
DM :: da_local
|
DM :: da_local
|
||||||
Vec :: x_local, coordinates
|
Vec :: x_local, coordinates
|
||||||
|
@ -639,24 +645,27 @@ subroutine formJacobian(da_local,x_local,Jac_pre,Jac,dummy,ierr)
|
||||||
PetscScalar,pointer,dimension(:,:,:,:) :: x_scal
|
PetscScalar,pointer,dimension(:,:,:,:) :: x_scal
|
||||||
PetscScalar,dimension(24,24) :: K_ele
|
PetscScalar,dimension(24,24) :: K_ele
|
||||||
PetscScalar,dimension(9,24) :: BMatFull
|
PetscScalar,dimension(9,24) :: BMatFull
|
||||||
PetscInt :: i, ii, j, jj, k, kk, ctr, ele
|
PetscInt :: i, ii, j, jj, k, kk, ctr, ce
|
||||||
PetscInt,dimension(3),parameter :: rows = [0, 1, 2]
|
PetscInt,dimension(3),parameter :: rows = [0, 1, 2]
|
||||||
PetscScalar :: diag
|
PetscScalar :: diag
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
MatNullSpace :: matnull
|
MatNullSpace :: matnull
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
BMatFull = 0.0
|
BMatFull = 0.0
|
||||||
BMatFull(1:3,1 :8 ) = BMat
|
BMatFull(1:3,1 :8 ) = BMat
|
||||||
BMatFull(4:6,9 :16) = BMat
|
BMatFull(4:6,9 :16) = BMat
|
||||||
BMatFull(7:9,17:24) = BMat
|
BMatFull(7:9,17:24) = BMat
|
||||||
call MatSetOption(Jac,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE,ierr); CHKERRQ(ierr)
|
call MatSetOption(Jac,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE,err_PETSc)
|
||||||
call MatSetOption(Jac,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call MatZeroEntries(Jac,ierr); CHKERRQ(ierr)
|
call MatSetOption(Jac,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE,err_PETSc)
|
||||||
ele = 0
|
CHKERRQ(err_PETSc)
|
||||||
do k = zstart, zend; do j = ystart, yend; do i = xstart, xend
|
call MatZeroEntries(Jac,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
ce = 0
|
||||||
|
do k = grid3offset+1, grid3offset+grid3; do j = 1, grid(2); do i = 1, grid(1)
|
||||||
ctr = 0
|
ctr = 0
|
||||||
do kk = 0, 1; do jj = 0, 1; do ii = 0, 1
|
do kk = -1, 0; do jj = -1, 0; do ii = -1, 0
|
||||||
ctr = ctr + 1
|
ctr = ctr + 1
|
||||||
col(MatStencil_i,ctr ) = i+ii
|
col(MatStencil_i,ctr ) = i+ii
|
||||||
col(MatStencil_j,ctr ) = j+jj
|
col(MatStencil_j,ctr ) = j+jj
|
||||||
|
@ -672,49 +681,60 @@ subroutine formJacobian(da_local,x_local,Jac_pre,Jac,dummy,ierr)
|
||||||
col(MatStencil_c,ctr+16) = 2
|
col(MatStencil_c,ctr+16) = 2
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
row = col
|
row = col
|
||||||
ele = ele + 1
|
ce = ce + 1
|
||||||
K_ele = 0.0
|
K_ele = 0.0
|
||||||
K_ele(1 :8 ,1 :8 ) = HGMat*(homogenization_dPdF(1,1,1,1,ele) + &
|
K_ele(1 :8 ,1 :8 ) = HGMat*(homogenization_dPdF(1,1,1,1,ce) + &
|
||||||
homogenization_dPdF(2,2,2,2,ele) + &
|
homogenization_dPdF(2,2,2,2,ce) + &
|
||||||
homogenization_dPdF(3,3,3,3,ele))/3.0_pReal
|
homogenization_dPdF(3,3,3,3,ce))/3.0_pReal
|
||||||
K_ele(9 :16,9 :16) = HGMat*(homogenization_dPdF(1,1,1,1,ele) + &
|
K_ele(9 :16,9 :16) = HGMat*(homogenization_dPdF(1,1,1,1,ce) + &
|
||||||
homogenization_dPdF(2,2,2,2,ele) + &
|
homogenization_dPdF(2,2,2,2,ce) + &
|
||||||
homogenization_dPdF(3,3,3,3,ele))/3.0_pReal
|
homogenization_dPdF(3,3,3,3,ce))/3.0_pReal
|
||||||
K_ele(17:24,17:24) = HGMat*(homogenization_dPdF(1,1,1,1,ele) + &
|
K_ele(17:24,17:24) = HGMat*(homogenization_dPdF(1,1,1,1,ce) + &
|
||||||
homogenization_dPdF(2,2,2,2,ele) + &
|
homogenization_dPdF(2,2,2,2,ce) + &
|
||||||
homogenization_dPdF(3,3,3,3,ele))/3.0_pReal
|
homogenization_dPdF(3,3,3,3,ce))/3.0_pReal
|
||||||
K_ele = K_ele + &
|
K_ele = K_ele + &
|
||||||
matmul(transpose(BMatFull), &
|
matmul(transpose(BMatFull), &
|
||||||
matmul(reshape(reshape(homogenization_dPdF(1:3,1:3,1:3,1:3,ele), &
|
matmul(reshape(reshape(homogenization_dPdF(1:3,1:3,1:3,1:3,ce), &
|
||||||
shape=[3,3,3,3], order=[2,1,4,3]),shape=[9,9]),BMatFull))*detJ
|
shape=[3,3,3,3], order=[2,1,4,3]),shape=[9,9]),BMatFull))*detJ
|
||||||
call MatSetValuesStencil(Jac,24,row,24,col,K_ele,ADD_VALUES,ierr)
|
call MatSetValuesStencil(Jac,24_pPETScInt,row,24_pPetscInt,col,K_ele,ADD_VALUES,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
call MatAssemblyBegin(Jac,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
call MatAssemblyBegin(Jac,MAT_FINAL_ASSEMBLY,err_PETSc)
|
||||||
call MatAssemblyEnd(Jac,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call MatAssemblyBegin(Jac_pre,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
call MatAssemblyEnd(Jac,MAT_FINAL_ASSEMBLY,err_PETSc)
|
||||||
call MatAssemblyEnd(Jac_pre,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call MatAssemblyBegin(Jac_pre,MAT_FINAL_ASSEMBLY,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call MatAssemblyEnd(Jac_pre,MAT_FINAL_ASSEMBLY,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! applying boundary conditions
|
! applying boundary conditions
|
||||||
diag = (C_volAvg(1,1,1,1)/delta(1)**2 + &
|
diag = (C_volAvg(1,1,1,1)/delta(1)**2 + C_volAvg(2,2,2,2)/delta(2)**2 + C_volAvg(3,3,3,3)/delta(3)**2) &
|
||||||
C_volAvg(2,2,2,2)/delta(2)**2 + &
|
* detJ
|
||||||
C_volAvg(3,3,3,3)/delta(3)**2)*detJ
|
call MatZeroRowsColumns(Jac,size(rows,kind=pPetscInt),rows,diag,PETSC_NULL_VEC,PETSC_NULL_VEC,err_PETSc)
|
||||||
call MatZeroRowsColumns(Jac,size(rows),rows,diag,PETSC_NULL_VEC,PETSC_NULL_VEC,ierr)
|
CHKERRQ(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
call DMGetGlobalVector(da_local,coordinates,err_PETSc)
|
||||||
call DMGetGlobalVector(da_local,coordinates,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDAVecGetArrayF90(da_local,coordinates,x_scal,ierr); CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da_local,coordinates,x_scal,err_PETSc)
|
||||||
ele = 0
|
CHKERRQ(err_PETSc)
|
||||||
do k = zstart, zend; do j = ystart, yend; do i = xstart, xend
|
ce = 0
|
||||||
ele = ele + 1
|
do k = grid3offset+1, grid3offset+grid3; do j = 1, grid(2); do i = 1, grid(1)
|
||||||
x_scal(0:2,i,j,k) = discretization_IPcoords(1:3,ele)
|
ce = ce + 1
|
||||||
|
x_scal(0:2,i-1,j-1,k-1) = discretization_IPcoords(1:3,ce)
|
||||||
enddo; enddo; enddo
|
enddo; enddo; enddo
|
||||||
call DMDAVecRestoreArrayF90(da_local,coordinates,x_scal,ierr); CHKERRQ(ierr) ! initialize to undeformed coordinates (ToDo: use ip coordinates)
|
call DMDAVecRestoreArrayF90(da_local,coordinates,x_scal,err_PETSc)
|
||||||
call MatNullSpaceCreateRigidBody(coordinates,matnull,ierr); CHKERRQ(ierr) ! get rigid body deformation modes
|
CHKERRQ(err_PETSc) ! initialize to undeformed coordinates (ToDo: use ip coordinates)
|
||||||
call DMRestoreGlobalVector(da_local,coordinates,ierr); CHKERRQ(ierr)
|
call MatNullSpaceCreateRigidBody(coordinates,matnull,err_PETSc)
|
||||||
call MatSetNullSpace(Jac,matnull,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc) ! get rigid body deformation modes
|
||||||
call MatSetNearNullSpace(Jac,matnull,ierr); CHKERRQ(ierr)
|
call DMRestoreGlobalVector(da_local,coordinates,err_PETSc)
|
||||||
call MatNullSpaceDestroy(matnull,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call MatSetNullSpace(Jac,matnull,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call MatSetNearNullSpace(Jac,matnull,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call MatNullSpaceDestroy(matnull,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine formJacobian
|
end subroutine formJacobian
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ module grid_mechanical_spectral_basic
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc data
|
! PETSc data
|
||||||
DM :: da
|
DM :: da
|
||||||
SNES :: snes
|
SNES :: SNES_mechanical
|
||||||
Vec :: solution_vec
|
Vec :: solution_vec
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -97,7 +97,8 @@ contains
|
||||||
subroutine grid_mechanical_spectral_basic_init
|
subroutine grid_mechanical_spectral_basic_init
|
||||||
|
|
||||||
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P
|
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
||||||
F ! pointer to solution data
|
F ! pointer to solution data
|
||||||
PetscInt, dimension(0:worldsize-1) :: localK
|
PetscInt, dimension(0:worldsize-1) :: localK
|
||||||
|
@ -145,10 +146,10 @@ subroutine grid_mechanical_spectral_basic_init
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! set default and user defined options for PETSc
|
! set default and user defined options for PETSc
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! allocate global fields
|
! allocate global fields
|
||||||
|
@ -157,33 +158,42 @@ subroutine grid_mechanical_spectral_basic_init
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! initialize solver specific parts of PETSc
|
! initialize solver specific parts of PETSc
|
||||||
call SNESCreate(PETSC_COMM_WORLD,snes,ierr); CHKERRQ(ierr)
|
call SNESCreate(PETSC_COMM_WORLD,SNES_mechanical,err_PETSc)
|
||||||
call SNESSetOptionsPrefix(snes,'mechanical_',ierr);CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
localK = 0
|
call SNESSetOptionsPrefix(SNES_mechanical,'mechanical_',err_PETSc)
|
||||||
localK(worldrank) = grid3
|
CHKERRQ(err_PETSc)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,ierr)
|
localK = 0_pPetscInt
|
||||||
|
localK(worldrank) = int(grid3,pPetscInt)
|
||||||
|
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call DMDACreate3d(PETSC_COMM_WORLD, &
|
call DMDACreate3d(PETSC_COMM_WORLD, &
|
||||||
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
||||||
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
||||||
grid(1),grid(2),grid(3), & ! global grid
|
int(grid(1),pPetscInt),int(grid(2),pPetscInt),int(grid(3),pPetscInt), & ! global grid
|
||||||
1 , 1, worldsize, &
|
1_pPetscInt, 1_pPetscInt, int(worldsize,pPetscInt), &
|
||||||
9, 0, & ! #dof (F tensor), ghost boundary width (domain overlap)
|
9_pPetscInt, 0_pPetscInt, & ! #dof (F, tensor), ghost boundary width (domain overlap)
|
||||||
[grid(1)],[grid(2)],localK, & ! local grid
|
[int(grid(1),pPetscInt)],[int(grid(2),pPetscInt)],localK, & ! local grid
|
||||||
da,ierr) ! handle, error
|
da,err_PETSc) ! handle, error
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetDM(snes,da,ierr); CHKERRQ(ierr) ! connect snes to da
|
call DMsetFromOptions(da,err_PETSc)
|
||||||
call DMsetFromOptions(da,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMsetUp(da,ierr); CHKERRQ(ierr)
|
call DMsetUp(da,err_PETSc)
|
||||||
call DMcreateGlobalVector(da,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 9, i.e. every def grad tensor)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDASNESsetFunctionLocal(da,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector
|
call DMcreateGlobalVector(da,solution_vec,err_PETSc) ! global solution vector (grid x 9, i.e. every def grad tensor)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESsetConvergenceTest(snes,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,ierr) ! specify custom convergence check function "converged"
|
call DMDASNESsetFunctionLocal(da,INSERT_VALUES,formResidual,PETSC_NULL_SNES,err_PETSc) ! residual vector of same shape as solution vector
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESsetFromOptions(snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments
|
call SNESsetConvergenceTest(SNES_mechanical,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,err_PETSc) ! specify custom convergence check function "converged"
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetDM(SNES_mechanical,da,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESsetFromOptions(SNES_mechanical,err_PETSc) ! pull it all together with additional CLI arguments
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! init fields
|
! init fields
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) ! places pointer on PETSc data
|
call DMDAVecGetArrayF90(da,solution_vec,F,err_PETSc) ! places pointer on PETSc data
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
restartRead: if (interface_restartInc > 0) then
|
restartRead: if (interface_restartInc > 0) then
|
||||||
print'(/,1x,a,i0,a)', 'reading restart data of increment ', interface_restartInc, ' from file'
|
print'(/,1x,a,i0,a)', 'reading restart data of increment ', interface_restartInc, ' from file'
|
||||||
|
@ -192,17 +202,17 @@ subroutine grid_mechanical_spectral_basic_init
|
||||||
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
||||||
|
|
||||||
call HDF5_read(P_aim,groupHandle,'P_aim',.false.)
|
call HDF5_read(P_aim,groupHandle,'P_aim',.false.)
|
||||||
call MPI_Bcast(P_aim,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(P_aim,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aim,groupHandle,'F_aim',.false.)
|
call HDF5_read(F_aim,groupHandle,'F_aim',.false.)
|
||||||
call MPI_Bcast(F_aim,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aim,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aim_lastInc,groupHandle,'F_aim_lastInc',.false.)
|
call HDF5_read(F_aim_lastInc,groupHandle,'F_aim_lastInc',.false.)
|
||||||
call MPI_Bcast(F_aim_lastInc,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aim_lastInc,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aimDot,groupHandle,'F_aimDot',.false.)
|
call HDF5_read(F_aimDot,groupHandle,'F_aimDot',.false.)
|
||||||
call MPI_Bcast(F_aimDot,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aimDot,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F,groupHandle,'F')
|
call HDF5_read(F,groupHandle,'F')
|
||||||
call HDF5_read(F_lastInc,groupHandle,'F_lastInc')
|
call HDF5_read(F_lastInc,groupHandle,'F_lastInc')
|
||||||
|
|
||||||
|
@ -216,24 +226,28 @@ subroutine grid_mechanical_spectral_basic_init
|
||||||
call utilities_constitutiveResponse(P,P_av,C_volAvg,C_minMaxAvg, & ! stress field, stress avg, global average of stiffness and (min+max)/2
|
call utilities_constitutiveResponse(P,P_av,C_volAvg,C_minMaxAvg, & ! stress field, stress avg, global average of stiffness and (min+max)/2
|
||||||
reshape(F,shape(F_lastInc)), & ! target F
|
reshape(F,shape(F_lastInc)), & ! target F
|
||||||
0.0_pReal) ! time increment
|
0.0_pReal) ! time increment
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) ! deassociate pointer
|
call DMDAVecRestoreArrayF90(da,solution_vec,F,err_PETSc) ! deassociate pointer
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
restartRead2: if (interface_restartInc > 0) then
|
restartRead2: if (interface_restartInc > 0) then
|
||||||
print'(1x,a,i0,a)', 'reading more restart data of increment ', interface_restartInc, ' from file'
|
print'(1x,a,i0,a)', 'reading more restart data of increment ', interface_restartInc, ' from file'
|
||||||
call HDF5_read(C_volAvg,groupHandle,'C_volAvg',.false.)
|
call HDF5_read(C_volAvg,groupHandle,'C_volAvg',.false.)
|
||||||
call MPI_Bcast(C_volAvg,81,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(C_volAvg,81_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(C_volAvgLastInc,groupHandle,'C_volAvgLastInc',.false.)
|
call HDF5_read(C_volAvgLastInc,groupHandle,'C_volAvgLastInc',.false.)
|
||||||
call MPI_Bcast(C_volAvgLastInc,81,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(C_volAvgLastInc,81_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
call HDF5_closeGroup(groupHandle)
|
call HDF5_closeGroup(groupHandle)
|
||||||
call HDF5_closeFile(fileHandle)
|
call HDF5_closeFile(fileHandle)
|
||||||
|
|
||||||
call MPI_File_open(MPI_COMM_WORLD, trim(getSolverJobName())//'.C_ref', &
|
call MPI_File_open(MPI_COMM_WORLD, trim(getSolverJobName())//'.C_ref', &
|
||||||
MPI_MODE_RDONLY,MPI_INFO_NULL,fileUnit,ierr)
|
MPI_MODE_RDONLY,MPI_INFO_NULL,fileUnit,err_MPI)
|
||||||
call MPI_File_read(fileUnit,C_minMaxAvg,81,MPI_DOUBLE,MPI_STATUS_IGNORE,ierr)
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call MPI_File_close(fileUnit,ierr)
|
call MPI_File_read(fileUnit,C_minMaxAvg,81_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_STATUS_IGNORE,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
call MPI_File_close(fileUnit,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
end if restartRead2
|
end if restartRead2
|
||||||
|
|
||||||
call utilities_updateGamma(C_minMaxAvg)
|
call utilities_updateGamma(C_minMaxAvg)
|
||||||
|
@ -255,7 +269,7 @@ function grid_mechanical_spectral_basic_solution(incInfoIn) result(solution)
|
||||||
solution
|
solution
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc Data
|
! PETSc Data
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
|
|
||||||
incInfo = incInfoIn
|
incInfo = incInfoIn
|
||||||
|
@ -265,13 +279,10 @@ function grid_mechanical_spectral_basic_solution(incInfoIn) result(solution)
|
||||||
S = utilities_maskedCompliance(params%rotation_BC,params%stress_mask,C_volAvg)
|
S = utilities_maskedCompliance(params%rotation_BC,params%stress_mask,C_volAvg)
|
||||||
if (num%update_gamma) call utilities_updateGamma(C_minMaxAvg)
|
if (num%update_gamma) call utilities_updateGamma(C_minMaxAvg)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
call SNESsolve(SNES_mechanical,PETSC_NULL_VEC,solution_vec,err_PETSc)
|
||||||
! solve BVP
|
CHKERRQ(err_PETSc)
|
||||||
call SNESsolve(snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr)
|
call SNESGetConvergedReason(SNES_mechanical,reason,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
!--------------------------------------------------------------------------------------------------
|
|
||||||
! check convergence
|
|
||||||
call SNESGetConvergedReason(snes,reason,ierr); CHKERRQ(ierr)
|
|
||||||
|
|
||||||
solution%converged = reason > 0
|
solution%converged = reason > 0
|
||||||
solution%iterationsNeeded = totalIter
|
solution%iterationsNeeded = totalIter
|
||||||
|
@ -301,11 +312,12 @@ subroutine grid_mechanical_spectral_basic_forward(cutBack,guess,Delta_t,Delta_t_
|
||||||
deformation_BC
|
deformation_BC
|
||||||
type(rotation), intent(in) :: &
|
type(rotation), intent(in) :: &
|
||||||
rotation_BC
|
rotation_BC
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
PetscScalar, pointer, dimension(:,:,:,:) :: F
|
PetscScalar, pointer, dimension(:,:,:,:) :: F
|
||||||
|
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da,solution_vec,F,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
if (cutBack) then
|
if (cutBack) then
|
||||||
C_volAvg = C_volAvgLastInc
|
C_volAvg = C_volAvgLastInc
|
||||||
|
@ -348,7 +360,8 @@ subroutine grid_mechanical_spectral_basic_forward(cutBack,guess,Delta_t,Delta_t_
|
||||||
|
|
||||||
F = reshape(utilities_forwardField(Delta_t,F_lastInc,Fdot, & ! estimate of F at end of time+Delta_t that matches rotated F_aim on average
|
F = reshape(utilities_forwardField(Delta_t,F_lastInc,Fdot, & ! estimate of F at end of time+Delta_t that matches rotated F_aim on average
|
||||||
rotation_BC%rotate(F_aim,active=.true.)),[9,grid(1),grid(2),grid3])
|
rotation_BC%rotate(F_aim,active=.true.)),[9,grid(1),grid(2),grid3])
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da,solution_vec,F,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! set module wide available data
|
! set module wide available data
|
||||||
|
@ -364,12 +377,14 @@ end subroutine grid_mechanical_spectral_basic_forward
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine grid_mechanical_spectral_basic_updateCoords
|
subroutine grid_mechanical_spectral_basic_updateCoords
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
PetscScalar, dimension(:,:,:,:), pointer :: F
|
PetscScalar, dimension(:,:,:,:), pointer :: F
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da,solution_vec,F,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
call utilities_updateCoords(F)
|
call utilities_updateCoords(F)
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da,solution_vec,F,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine grid_mechanical_spectral_basic_updateCoords
|
end subroutine grid_mechanical_spectral_basic_updateCoords
|
||||||
|
|
||||||
|
@ -379,11 +394,12 @@ end subroutine grid_mechanical_spectral_basic_updateCoords
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine grid_mechanical_spectral_basic_restartWrite
|
subroutine grid_mechanical_spectral_basic_restartWrite
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer(HID_T) :: fileHandle, groupHandle
|
integer(HID_T) :: fileHandle, groupHandle
|
||||||
PetscScalar, dimension(:,:,:,:), pointer :: F
|
PetscScalar, dimension(:,:,:,:), pointer :: F
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da,solution_vec,F,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
print'(1x,a)', 'writing solver data required for restart to file'; flush(IO_STDOUT)
|
print'(1x,a)', 'writing solver data required for restart to file'; flush(IO_STDOUT)
|
||||||
|
|
||||||
|
@ -410,7 +426,8 @@ subroutine grid_mechanical_spectral_basic_restartWrite
|
||||||
|
|
||||||
if (num%update_gamma) call utilities_saveReferenceStiffness
|
if (num%update_gamma) call utilities_saveReferenceStiffness
|
||||||
|
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da,solution_vec,F,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine grid_mechanical_spectral_basic_restartWrite
|
end subroutine grid_mechanical_spectral_basic_restartWrite
|
||||||
|
|
||||||
|
@ -418,7 +435,7 @@ end subroutine grid_mechanical_spectral_basic_restartWrite
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief convergence check
|
!> @brief convergence check
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dummy,ierr)
|
subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dummy,err_PETSc)
|
||||||
|
|
||||||
SNES :: snes_local
|
SNES :: snes_local
|
||||||
PetscInt, intent(in) :: PETScIter
|
PetscInt, intent(in) :: PETScIter
|
||||||
|
@ -428,7 +445,7 @@ subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dumm
|
||||||
devNull3
|
devNull3
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
real(pReal) :: &
|
real(pReal) :: &
|
||||||
divTol, &
|
divTol, &
|
||||||
BCTol
|
BCTol
|
||||||
|
@ -452,6 +469,7 @@ subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dumm
|
||||||
err_BC/BCTol, ' (',err_BC, ' Pa, tol = ',BCTol,')'
|
err_BC/BCTol, ' (',err_BC, ' Pa, tol = ',BCTol,')'
|
||||||
print'(/,1x,a)', '==========================================================================='
|
print'(/,1x,a)', '==========================================================================='
|
||||||
flush(IO_STDOUT)
|
flush(IO_STDOUT)
|
||||||
|
err_PETSc = 0
|
||||||
|
|
||||||
end subroutine converged
|
end subroutine converged
|
||||||
|
|
||||||
|
@ -460,23 +478,26 @@ end subroutine converged
|
||||||
!> @brief forms the residual vector
|
!> @brief forms the residual vector
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine formResidual(in, F, &
|
subroutine formResidual(in, F, &
|
||||||
residuum, dummy, ierr)
|
r, dummy, err_PETSc)
|
||||||
|
|
||||||
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: in !< DMDA info (needs to be named "in" for macros like XRANGE to work)
|
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: in !< DMDA info (needs to be named "in" for macros like XRANGE to work)
|
||||||
PetscScalar, dimension(3,3,XG_RANGE,YG_RANGE,ZG_RANGE), &
|
PetscScalar, dimension(3,3,XG_RANGE,YG_RANGE,ZG_RANGE), &
|
||||||
intent(in) :: F !< deformation gradient field
|
intent(in) :: F !< deformation gradient field
|
||||||
PetscScalar, dimension(3,3,X_RANGE,Y_RANGE,Z_RANGE), &
|
PetscScalar, dimension(3,3,X_RANGE,Y_RANGE,Z_RANGE), &
|
||||||
intent(out) :: residuum !< residuum field
|
intent(out) :: r !< residuum field
|
||||||
real(pReal), dimension(3,3) :: &
|
real(pReal), dimension(3,3) :: &
|
||||||
deltaF_aim
|
deltaF_aim
|
||||||
PetscInt :: &
|
PetscInt :: &
|
||||||
PETScIter, &
|
PETScIter, &
|
||||||
nfuncs
|
nfuncs
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
call SNESGetNumberFunctionEvals(snes,nfuncs,ierr); CHKERRQ(ierr)
|
call SNESGetNumberFunctionEvals(SNES_mechanical,nfuncs,err_PETSc)
|
||||||
call SNESGetIterationNumber(snes,PETScIter,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESGetIterationNumber(SNES_mechanical,PETScIter,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment
|
if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment
|
||||||
|
|
||||||
|
@ -494,10 +515,11 @@ subroutine formResidual(in, F, &
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! evaluate constitutive response
|
! evaluate constitutive response
|
||||||
call utilities_constitutiveResponse(residuum, & ! "residuum" gets field of first PK stress (to save memory)
|
call utilities_constitutiveResponse(r, & ! residuum gets field of first PK stress (to save memory)
|
||||||
P_av,C_volAvg,C_minMaxAvg, &
|
P_av,C_volAvg,C_minMaxAvg, &
|
||||||
F,params%Delta_t,params%rotation_BC)
|
F,params%Delta_t,params%rotation_BC)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! stress BC handling
|
! stress BC handling
|
||||||
|
@ -508,7 +530,7 @@ subroutine formResidual(in, F, &
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! updated deformation gradient using fix point algorithm of basic scheme
|
! updated deformation gradient using fix point algorithm of basic scheme
|
||||||
tensorField_real = 0.0_pReal
|
tensorField_real = 0.0_pReal
|
||||||
tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) = residuum ! store fPK field for subsequent FFT forward transform
|
tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) = r ! store fPK field for subsequent FFT forward transform
|
||||||
call utilities_FFTtensorForward ! FFT forward of global "tensorField_real"
|
call utilities_FFTtensorForward ! FFT forward of global "tensorField_real"
|
||||||
err_div = utilities_divergenceRMS() ! divRMS of tensorField_fourier for later use
|
err_div = utilities_divergenceRMS() ! divRMS of tensorField_fourier for later use
|
||||||
call utilities_fourierGammaConvolution(params%rotation_BC%rotate(deltaF_aim,active=.true.)) ! convolution of Gamma and tensorField_fourier
|
call utilities_fourierGammaConvolution(params%rotation_BC%rotate(deltaF_aim,active=.true.)) ! convolution of Gamma and tensorField_fourier
|
||||||
|
@ -516,7 +538,7 @@ subroutine formResidual(in, F, &
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! constructing residual
|
! constructing residual
|
||||||
residuum = tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) ! Gamma*P gives correction towards div(P) = 0, so needs to be zero, too
|
r = tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) ! Gamma*P gives correction towards div(P) = 0, so needs to be zero, too
|
||||||
|
|
||||||
end subroutine formResidual
|
end subroutine formResidual
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ module grid_mechanical_spectral_polarisation
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc data
|
! PETSc data
|
||||||
DM :: da
|
DM :: da
|
||||||
SNES :: snes
|
SNES :: SNES_mechanical
|
||||||
Vec :: solution_vec
|
Vec :: solution_vec
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -108,7 +108,8 @@ contains
|
||||||
subroutine grid_mechanical_spectral_polarisation_init
|
subroutine grid_mechanical_spectral_polarisation_init
|
||||||
|
|
||||||
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P
|
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
PetscScalar, pointer, dimension(:,:,:,:) :: &
|
||||||
FandF_tau, & ! overall pointer to solution data
|
FandF_tau, & ! overall pointer to solution data
|
||||||
F, & ! specific (sub)pointer
|
F, & ! specific (sub)pointer
|
||||||
|
@ -163,10 +164,10 @@ subroutine grid_mechanical_spectral_polarisation_init
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! set default and user defined options for PETSc
|
! set default and user defined options for PETSc
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! allocate global fields
|
! allocate global fields
|
||||||
|
@ -177,33 +178,42 @@ subroutine grid_mechanical_spectral_polarisation_init
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! initialize solver specific parts of PETSc
|
! initialize solver specific parts of PETSc
|
||||||
call SNESCreate(PETSC_COMM_WORLD,snes,ierr); CHKERRQ(ierr)
|
call SNESCreate(PETSC_COMM_WORLD,SNES_mechanical,err_PETSc)
|
||||||
call SNESSetOptionsPrefix(snes,'mechanical_',ierr);CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
localK = 0
|
call SNESSetOptionsPrefix(SNES_mechanical,'mechanical_',err_PETSc)
|
||||||
localK(worldrank) = grid3
|
CHKERRQ(err_PETSc)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,ierr)
|
localK = 0_pPetscInt
|
||||||
|
localK(worldrank) = int(grid3,pPetscInt)
|
||||||
|
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call DMDACreate3d(PETSC_COMM_WORLD, &
|
call DMDACreate3d(PETSC_COMM_WORLD, &
|
||||||
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
||||||
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
||||||
grid(1),grid(2),grid(3), & ! global grid
|
int(grid(1),pPetscInt),int(grid(2),pPetscInt),int(grid(3),pPetscInt), & ! global grid
|
||||||
1 , 1, worldsize, &
|
1_pPetscInt, 1_pPetscInt, int(worldsize,pPetscInt), &
|
||||||
18, 0, & ! #dof (F tensor), ghost boundary width (domain overlap)
|
18_pPetscInt, 0_pPetscInt, & ! #dof (2xtensor), ghost boundary width (domain overlap)
|
||||||
[grid(1)],[grid(2)],localK, & ! local grid
|
[int(grid(1),pPetscInt)],[int(grid(2),pPetscInt)],localK, & ! local grid
|
||||||
da,ierr) ! handle, error
|
da,err_PETSc) ! handle, error
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetDM(snes,da,ierr); CHKERRQ(ierr) ! connect snes to da
|
call DMsetFromOptions(da,err_PETSc)
|
||||||
call DMsetFromOptions(da,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMsetUp(da,ierr); CHKERRQ(ierr)
|
call DMsetUp(da,err_PETSc)
|
||||||
call DMcreateGlobalVector(da,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 18, i.e. every def grad tensor)
|
CHKERRQ(err_PETSc)
|
||||||
call DMDASNESsetFunctionLocal(da,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector
|
call DMcreateGlobalVector(da,solution_vec,err_PETSc) ! global solution vector (grid x 18, i.e. every def grad tensor)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESsetConvergenceTest(snes,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,ierr) ! specify custom convergence check function "converged"
|
call DMDASNESsetFunctionLocal(da,INSERT_VALUES,formResidual,PETSC_NULL_SNES,err_PETSc) ! residual vector of same shape as solution vector
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESsetFromOptions(snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments
|
call SNESsetConvergenceTest(SNES_mechanical,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,err_PETSc) ! specify custom convergence check function "converged"
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetDM(SNES_mechanical,da,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESsetFromOptions(SNES_mechanical,err_PETSc) ! pull it all together with additional CLI arguments
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! init fields
|
! init fields
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) ! places pointer on PETSc data
|
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,err_PETSc) ! places pointer on PETSc data
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
F => FandF_tau(0: 8,:,:,:)
|
F => FandF_tau(0: 8,:,:,:)
|
||||||
F_tau => FandF_tau(9:17,:,:,:)
|
F_tau => FandF_tau(9:17,:,:,:)
|
||||||
|
|
||||||
|
@ -214,17 +224,17 @@ subroutine grid_mechanical_spectral_polarisation_init
|
||||||
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
||||||
|
|
||||||
call HDF5_read(P_aim,groupHandle,'P_aim',.false.)
|
call HDF5_read(P_aim,groupHandle,'P_aim',.false.)
|
||||||
call MPI_Bcast(P_aim,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(P_aim,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aim,groupHandle,'F_aim',.false.)
|
call HDF5_read(F_aim,groupHandle,'F_aim',.false.)
|
||||||
call MPI_Bcast(F_aim,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aim,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aim_lastInc,groupHandle,'F_aim_lastInc',.false.)
|
call HDF5_read(F_aim_lastInc,groupHandle,'F_aim_lastInc',.false.)
|
||||||
call MPI_Bcast(F_aim_lastInc,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aim_lastInc,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F_aimDot,groupHandle,'F_aimDot',.false.)
|
call HDF5_read(F_aimDot,groupHandle,'F_aimDot',.false.)
|
||||||
call MPI_Bcast(F_aimDot,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(F_aimDot,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(F,groupHandle,'F')
|
call HDF5_read(F,groupHandle,'F')
|
||||||
call HDF5_read(F_lastInc,groupHandle,'F_lastInc')
|
call HDF5_read(F_lastInc,groupHandle,'F_lastInc')
|
||||||
call HDF5_read(F_tau,groupHandle,'F_tau')
|
call HDF5_read(F_tau,groupHandle,'F_tau')
|
||||||
|
@ -242,24 +252,28 @@ subroutine grid_mechanical_spectral_polarisation_init
|
||||||
call utilities_constitutiveResponse(P,P_av,C_volAvg,C_minMaxAvg, & ! stress field, stress avg, global average of stiffness and (min+max)/2
|
call utilities_constitutiveResponse(P,P_av,C_volAvg,C_minMaxAvg, & ! stress field, stress avg, global average of stiffness and (min+max)/2
|
||||||
reshape(F,shape(F_lastInc)), & ! target F
|
reshape(F,shape(F_lastInc)), & ! target F
|
||||||
0.0_pReal) ! time increment
|
0.0_pReal) ! time increment
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) ! deassociate pointer
|
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,err_PETSc) ! deassociate pointer
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
restartRead2: if (interface_restartInc > 0) then
|
restartRead2: if (interface_restartInc > 0) then
|
||||||
print'(1x,a,i0,a)', 'reading more restart data of increment ', interface_restartInc, ' from file'
|
print'(1x,a,i0,a)', 'reading more restart data of increment ', interface_restartInc, ' from file'
|
||||||
call HDF5_read(C_volAvg,groupHandle,'C_volAvg',.false.)
|
call HDF5_read(C_volAvg,groupHandle,'C_volAvg',.false.)
|
||||||
call MPI_Bcast(C_volAvg,81,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(C_volAvg,81_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call HDF5_read(C_volAvgLastInc,groupHandle,'C_volAvgLastInc',.false.)
|
call HDF5_read(C_volAvgLastInc,groupHandle,'C_volAvgLastInc',.false.)
|
||||||
call MPI_Bcast(C_volAvgLastInc,81,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(C_volAvgLastInc,81_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
call HDF5_closeGroup(groupHandle)
|
call HDF5_closeGroup(groupHandle)
|
||||||
call HDF5_closeFile(fileHandle)
|
call HDF5_closeFile(fileHandle)
|
||||||
|
|
||||||
call MPI_File_open(MPI_COMM_WORLD, trim(getSolverJobName())//'.C_ref', &
|
call MPI_File_open(MPI_COMM_WORLD, trim(getSolverJobName())//'.C_ref', &
|
||||||
MPI_MODE_RDONLY,MPI_INFO_NULL,fileUnit,ierr)
|
MPI_MODE_RDONLY,MPI_INFO_NULL,fileUnit,err_MPI)
|
||||||
call MPI_File_read(fileUnit,C_minMaxAvg,81,MPI_DOUBLE,MPI_STATUS_IGNORE,ierr)
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call MPI_File_close(fileUnit,ierr)
|
call MPI_File_read(fileUnit,C_minMaxAvg,81_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_STATUS_IGNORE,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
call MPI_File_close(fileUnit,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
end if restartRead2
|
end if restartRead2
|
||||||
|
|
||||||
call utilities_updateGamma(C_minMaxAvg)
|
call utilities_updateGamma(C_minMaxAvg)
|
||||||
|
@ -283,7 +297,7 @@ function grid_mechanical_spectral_polarisation_solution(incInfoIn) result(soluti
|
||||||
solution
|
solution
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc Data
|
! PETSc Data
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
|
|
||||||
incInfo = incInfoIn
|
incInfo = incInfoIn
|
||||||
|
@ -297,13 +311,10 @@ function grid_mechanical_spectral_polarisation_solution(incInfoIn) result(soluti
|
||||||
S_scale = math_invSym3333(C_minMaxAvg)
|
S_scale = math_invSym3333(C_minMaxAvg)
|
||||||
end if
|
end if
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
call SNESSolve(SNES_mechanical,PETSC_NULL_VEC,solution_vec,err_PETSc)
|
||||||
! solve BVP
|
CHKERRQ(err_PETSc)
|
||||||
call SNESsolve(snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr)
|
call SNESGetConvergedReason(SNES_mechanical,reason,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
!--------------------------------------------------------------------------------------------------
|
|
||||||
! check convergence
|
|
||||||
call SNESGetConvergedReason(snes,reason,ierr); CHKERRQ(ierr)
|
|
||||||
|
|
||||||
solution%converged = reason > 0
|
solution%converged = reason > 0
|
||||||
solution%iterationsNeeded = totalIter
|
solution%iterationsNeeded = totalIter
|
||||||
|
@ -333,13 +344,14 @@ subroutine grid_mechanical_spectral_polarisation_forward(cutBack,guess,Delta_t,D
|
||||||
deformation_BC
|
deformation_BC
|
||||||
type(rotation), intent(in) :: &
|
type(rotation), intent(in) :: &
|
||||||
rotation_BC
|
rotation_BC
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
PetscScalar, pointer, dimension(:,:,:,:) :: FandF_tau, F, F_tau
|
PetscScalar, pointer, dimension(:,:,:,:) :: FandF_tau, F, F_tau
|
||||||
integer :: i, j, k
|
integer :: i, j, k
|
||||||
real(pReal), dimension(3,3) :: F_lambda33
|
real(pReal), dimension(3,3) :: F_lambda33
|
||||||
|
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
F => FandF_tau(0: 8,:,:,:)
|
F => FandF_tau(0: 8,:,:,:)
|
||||||
F_tau => FandF_tau(9:17,:,:,:)
|
F_tau => FandF_tau(9:17,:,:,:)
|
||||||
|
|
||||||
|
@ -402,7 +414,8 @@ subroutine grid_mechanical_spectral_polarisation_forward(cutBack,guess,Delta_t,D
|
||||||
end do; end do; end do
|
end do; end do; end do
|
||||||
end if
|
end if
|
||||||
|
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! set module wide available data
|
! set module wide available data
|
||||||
|
@ -418,12 +431,14 @@ end subroutine grid_mechanical_spectral_polarisation_forward
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine grid_mechanical_spectral_polarisation_updateCoords
|
subroutine grid_mechanical_spectral_polarisation_updateCoords
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau
|
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
call utilities_updateCoords(FandF_tau(0:8,:,:,:))
|
call utilities_updateCoords(FandF_tau(0:8,:,:,:))
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine grid_mechanical_spectral_polarisation_updateCoords
|
end subroutine grid_mechanical_spectral_polarisation_updateCoords
|
||||||
|
|
||||||
|
@ -433,11 +448,12 @@ end subroutine grid_mechanical_spectral_polarisation_updateCoords
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine grid_mechanical_spectral_polarisation_restartWrite
|
subroutine grid_mechanical_spectral_polarisation_restartWrite
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer(HID_T) :: fileHandle, groupHandle
|
integer(HID_T) :: fileHandle, groupHandle
|
||||||
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau, F, F_tau
|
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau, F, F_tau
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
|
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
F => FandF_tau(0: 8,:,:,:)
|
F => FandF_tau(0: 8,:,:,:)
|
||||||
F_tau => FandF_tau(9:17,:,:,:)
|
F_tau => FandF_tau(9:17,:,:,:)
|
||||||
|
|
||||||
|
@ -467,7 +483,8 @@ subroutine grid_mechanical_spectral_polarisation_restartWrite
|
||||||
|
|
||||||
if (num%update_gamma) call utilities_saveReferenceStiffness
|
if (num%update_gamma) call utilities_saveReferenceStiffness
|
||||||
|
|
||||||
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
|
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine grid_mechanical_spectral_polarisation_restartWrite
|
end subroutine grid_mechanical_spectral_polarisation_restartWrite
|
||||||
|
|
||||||
|
@ -475,7 +492,7 @@ end subroutine grid_mechanical_spectral_polarisation_restartWrite
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief convergence check
|
!> @brief convergence check
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dummy,ierr)
|
subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dummy,err_PETSc)
|
||||||
|
|
||||||
SNES :: snes_local
|
SNES :: snes_local
|
||||||
PetscInt, intent(in) :: PETScIter
|
PetscInt, intent(in) :: PETScIter
|
||||||
|
@ -485,7 +502,7 @@ subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dumm
|
||||||
devNull3
|
devNull3
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
real(pReal) :: &
|
real(pReal) :: &
|
||||||
curlTol, &
|
curlTol, &
|
||||||
divTol, &
|
divTol, &
|
||||||
|
@ -513,6 +530,7 @@ subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dumm
|
||||||
err_BC/BCTol, ' (',err_BC, ' Pa, tol = ',BCTol,')'
|
err_BC/BCTol, ' (',err_BC, ' Pa, tol = ',BCTol,')'
|
||||||
print'(/,1x,a)', '==========================================================================='
|
print'(/,1x,a)', '==========================================================================='
|
||||||
flush(IO_STDOUT)
|
flush(IO_STDOUT)
|
||||||
|
err_PETSc = 0
|
||||||
|
|
||||||
end subroutine converged
|
end subroutine converged
|
||||||
|
|
||||||
|
@ -521,23 +539,24 @@ end subroutine converged
|
||||||
!> @brief forms the residual vector
|
!> @brief forms the residual vector
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine formResidual(in, FandF_tau, &
|
subroutine formResidual(in, FandF_tau, &
|
||||||
residuum, dummy,ierr)
|
r, dummy,err_PETSc)
|
||||||
|
|
||||||
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: in !< DMDA info (needs to be named "in" for macros like XRANGE to work)
|
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: in !< DMDA info (needs to be named "in" for macros like XRANGE to work)
|
||||||
PetscScalar, dimension(3,3,2,XG_RANGE,YG_RANGE,ZG_RANGE), &
|
PetscScalar, dimension(3,3,2,XG_RANGE,YG_RANGE,ZG_RANGE), &
|
||||||
target, intent(in) :: FandF_tau
|
target, intent(in) :: FandF_tau
|
||||||
PetscScalar, dimension(3,3,2,X_RANGE,Y_RANGE,Z_RANGE),&
|
PetscScalar, dimension(3,3,2,X_RANGE,Y_RANGE,Z_RANGE),&
|
||||||
target, intent(out) :: residuum !< residuum field
|
target, intent(out) :: r !< residuum field
|
||||||
PetscScalar, pointer, dimension(:,:,:,:,:) :: &
|
PetscScalar, pointer, dimension(:,:,:,:,:) :: &
|
||||||
F, &
|
F, &
|
||||||
F_tau, &
|
F_tau, &
|
||||||
residual_F, &
|
r_F, &
|
||||||
residual_F_tau
|
r_F_tau
|
||||||
PetscInt :: &
|
PetscInt :: &
|
||||||
PETScIter, &
|
PETScIter, &
|
||||||
nfuncs
|
nfuncs
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
integer :: &
|
integer :: &
|
||||||
i, j, k, e
|
i, j, k, e
|
||||||
|
|
||||||
|
@ -547,16 +566,19 @@ subroutine formResidual(in, FandF_tau, &
|
||||||
XG_RANGE,YG_RANGE,ZG_RANGE)
|
XG_RANGE,YG_RANGE,ZG_RANGE)
|
||||||
F_tau => FandF_tau(1:3,1:3,2,&
|
F_tau => FandF_tau(1:3,1:3,2,&
|
||||||
XG_RANGE,YG_RANGE,ZG_RANGE)
|
XG_RANGE,YG_RANGE,ZG_RANGE)
|
||||||
residual_F => residuum(1:3,1:3,1,&
|
r_F => r(1:3,1:3,1,&
|
||||||
X_RANGE, Y_RANGE, Z_RANGE)
|
X_RANGE, Y_RANGE, Z_RANGE)
|
||||||
residual_F_tau => residuum(1:3,1:3,2,&
|
r_F_tau => r(1:3,1:3,2,&
|
||||||
X_RANGE, Y_RANGE, Z_RANGE)
|
X_RANGE, Y_RANGE, Z_RANGE)
|
||||||
|
|
||||||
F_av = sum(sum(sum(F,dim=5),dim=4),dim=3) * wgt
|
F_av = sum(sum(sum(F,dim=5),dim=4),dim=3) * wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,F_av,9,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,F_av,9_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
call SNESGetNumberFunctionEvals(snes,nfuncs,ierr); CHKERRQ(ierr)
|
call SNESGetNumberFunctionEvals(SNES_mechanical,nfuncs,err_PETSc)
|
||||||
call SNESGetIterationNumber(snes,PETScIter,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESGetIterationNumber(SNES_mechanical,PETScIter,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment
|
if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment
|
||||||
|
|
||||||
|
@ -590,14 +612,14 @@ subroutine formResidual(in, FandF_tau, &
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! constructing residual
|
! constructing residual
|
||||||
residual_F_tau = num%beta*F - tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3)
|
r_F_tau = num%beta*F - tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! evaluate constitutive response
|
! evaluate constitutive response
|
||||||
call utilities_constitutiveResponse(residual_F, & ! "residuum" gets field of first PK stress (to save memory)
|
call utilities_constitutiveResponse(r_F, & ! "residuum" gets field of first PK stress (to save memory)
|
||||||
P_av,C_volAvg,C_minMaxAvg, &
|
P_av,C_volAvg,C_minMaxAvg, &
|
||||||
F - residual_F_tau/num%beta,params%Delta_t,params%rotation_BC)
|
F - r_F_tau/num%beta,params%Delta_t,params%rotation_BC)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! stress BC handling
|
! stress BC handling
|
||||||
|
@ -607,7 +629,7 @@ subroutine formResidual(in, FandF_tau, &
|
||||||
params%stress_mask)))
|
params%stress_mask)))
|
||||||
! calculate divergence
|
! calculate divergence
|
||||||
tensorField_real = 0.0_pReal
|
tensorField_real = 0.0_pReal
|
||||||
tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) = residual_F !< stress field in disguise
|
tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) = r_F !< stress field in disguise
|
||||||
call utilities_FFTtensorForward
|
call utilities_FFTtensorForward
|
||||||
err_div = utilities_divergenceRMS() !< root mean squared error in divergence of stress
|
err_div = utilities_divergenceRMS() !< root mean squared error in divergence of stress
|
||||||
|
|
||||||
|
@ -616,11 +638,11 @@ subroutine formResidual(in, FandF_tau, &
|
||||||
e = 0
|
e = 0
|
||||||
do k = 1, grid3; do j = 1, grid(2); do i = 1, grid(1)
|
do k = 1, grid3; do j = 1, grid(2); do i = 1, grid(1)
|
||||||
e = e + 1
|
e = e + 1
|
||||||
residual_F(1:3,1:3,i,j,k) = &
|
r_F(1:3,1:3,i,j,k) = &
|
||||||
math_mul3333xx33(math_invSym3333(homogenization_dPdF(1:3,1:3,1:3,1:3,e) + C_scale), &
|
math_mul3333xx33(math_invSym3333(homogenization_dPdF(1:3,1:3,1:3,1:3,e) + C_scale), &
|
||||||
residual_F(1:3,1:3,i,j,k) - matmul(F(1:3,1:3,i,j,k), &
|
r_F(1:3,1:3,i,j,k) - matmul(F(1:3,1:3,i,j,k), &
|
||||||
math_mul3333xx33(C_scale,F_tau(1:3,1:3,i,j,k) - F(1:3,1:3,i,j,k) - math_I3))) &
|
math_mul3333xx33(C_scale,F_tau(1:3,1:3,i,j,k) - F(1:3,1:3,i,j,k) - math_I3))) &
|
||||||
+ residual_F_tau(1:3,1:3,i,j,k)
|
+ r_F_tau(1:3,1:3,i,j,k)
|
||||||
end do; end do; end do
|
end do; end do; end do
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -38,9 +38,8 @@ module grid_thermal_spectral
|
||||||
type(tSolutionParams) :: params
|
type(tSolutionParams) :: params
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! PETSc data
|
! PETSc data
|
||||||
SNES :: thermal_snes
|
SNES :: SNES_thermal
|
||||||
Vec :: solution_vec
|
Vec :: solution_vec
|
||||||
PetscInt :: xstart, xend, ystart, yend, zstart, zend
|
|
||||||
real(pReal), dimension(:,:,:), allocatable :: &
|
real(pReal), dimension(:,:,:), allocatable :: &
|
||||||
T_current, & !< field of current temperature
|
T_current, & !< field of current temperature
|
||||||
T_lastInc, & !< field of previous temperature
|
T_lastInc, & !< field of previous temperature
|
||||||
|
@ -71,7 +70,8 @@ subroutine grid_thermal_spectral_init(T_0)
|
||||||
integer :: i, j, k, ce
|
integer :: i, j, k, ce
|
||||||
DM :: thermal_grid
|
DM :: thermal_grid
|
||||||
PetscScalar, dimension(:,:,:), pointer :: T_PETSc
|
PetscScalar, dimension(:,:,:), pointer :: T_PETSc
|
||||||
PetscErrorCode :: ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
PetscErrorCode :: err_PETSc
|
||||||
class(tNode), pointer :: &
|
class(tNode), pointer :: &
|
||||||
num_grid
|
num_grid
|
||||||
|
|
||||||
|
@ -94,60 +94,61 @@ subroutine grid_thermal_spectral_init(T_0)
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! set default and user defined options for PETSc
|
! set default and user defined options for PETSc
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-thermal_snes_type newtonls -thermal_snes_mf &
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-thermal_snes_type newtonls -thermal_snes_mf &
|
||||||
&-thermal_snes_ksp_ew -thermal_ksp_type fgmres',ierr)
|
&-thermal_snes_ksp_ew -thermal_ksp_type fgmres',err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
|
||||||
! initialize solver specific parts of PETSc
|
|
||||||
call SNESCreate(PETSC_COMM_WORLD,thermal_snes,ierr); CHKERRQ(ierr)
|
|
||||||
call SNESSetOptionsPrefix(thermal_snes,'thermal_',ierr);CHKERRQ(ierr)
|
|
||||||
localK = 0
|
|
||||||
localK(worldrank) = grid3
|
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,ierr)
|
|
||||||
call DMDACreate3D(PETSC_COMM_WORLD, &
|
|
||||||
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
|
||||||
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
|
||||||
grid(1),grid(2),grid(3), & ! global grid
|
|
||||||
1, 1, worldsize, &
|
|
||||||
1, 0, & ! #dof (T field), ghost boundary width (domain overlap)
|
|
||||||
[grid(1)],[grid(2)],localK, & ! local grid
|
|
||||||
thermal_grid,ierr) ! handle, error
|
|
||||||
CHKERRQ(ierr)
|
|
||||||
call SNESSetDM(thermal_snes,thermal_grid,ierr); CHKERRQ(ierr) ! connect snes to da
|
|
||||||
call DMsetFromOptions(thermal_grid,ierr); CHKERRQ(ierr)
|
|
||||||
call DMsetUp(thermal_grid,ierr); CHKERRQ(ierr)
|
|
||||||
call DMCreateGlobalVector(thermal_grid,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 1, i.e. every def grad tensor)
|
|
||||||
call DMDASNESSetFunctionLocal(thermal_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector
|
|
||||||
CHKERRQ(ierr)
|
|
||||||
call SNESSetFromOptions(thermal_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments
|
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! init fields
|
! init fields
|
||||||
call DMDAGetCorners(thermal_grid,xstart,ystart,zstart,xend,yend,zend,ierr)
|
allocate(T_current(grid(1),grid(2),grid3), source=T_0)
|
||||||
CHKERRQ(ierr)
|
allocate(T_lastInc(grid(1),grid(2),grid3), source=T_0)
|
||||||
xend = xstart + xend - 1
|
allocate(T_stagInc(grid(1),grid(2),grid3), source=T_0)
|
||||||
yend = ystart + yend - 1
|
|
||||||
zend = zstart + zend - 1
|
|
||||||
allocate(T_current(grid(1),grid(2),grid3), source=0.0_pReal)
|
|
||||||
allocate(T_lastInc(grid(1),grid(2),grid3), source=0.0_pReal)
|
|
||||||
allocate(T_stagInc(grid(1),grid(2),grid3), source=0.0_pReal)
|
|
||||||
|
|
||||||
ce = 0
|
ce = 0
|
||||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||||
ce = ce + 1
|
ce = ce + 1
|
||||||
T_current(i,j,k) = T_0
|
|
||||||
T_lastInc(i,j,k) = T_current(i,j,k)
|
|
||||||
T_stagInc(i,j,k) = T_current(i,j,k)
|
|
||||||
call homogenization_thermal_setField(T_0,0.0_pReal,ce)
|
call homogenization_thermal_setField(T_0,0.0_pReal,ce)
|
||||||
end do; end do; end do
|
end do; end do; end do
|
||||||
|
|
||||||
call DMDAVecGetArrayF90(thermal_grid,solution_vec,T_PETSc,ierr); CHKERRQ(ierr)
|
!--------------------------------------------------------------------------------------------------
|
||||||
T_PETSc(xstart:xend,ystart:yend,zstart:zend) = T_current
|
! initialize solver specific parts of PETSc
|
||||||
call DMDAVecRestoreArrayF90(thermal_grid,solution_vec,T_PETSc,ierr); CHKERRQ(ierr)
|
call SNESCreate(PETSC_COMM_WORLD,SNES_thermal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetOptionsPrefix(SNES_thermal,'thermal_',err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
localK = 0_pPetscInt
|
||||||
|
localK(worldrank) = int(grid3,pPetscInt)
|
||||||
|
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
call DMDACreate3D(PETSC_COMM_WORLD, &
|
||||||
|
DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, & ! cut off stencil at boundary
|
||||||
|
DMDA_STENCIL_BOX, & ! Moore (26) neighborhood around central point
|
||||||
|
int(grid(1),pPetscInt),int(grid(2),pPetscInt),int(grid(3),pPetscInt), & ! global grid
|
||||||
|
1_pPetscInt, 1_pPetscInt, int(worldsize,pPetscInt), &
|
||||||
|
1_pPetscInt, 0_pPetscInt, & ! #dof (T, scalar), ghost boundary width (domain overlap)
|
||||||
|
[int(grid(1),pPetscInt)],[int(grid(2),pPetscInt)],localK, & ! local grid
|
||||||
|
thermal_grid,err_PETSc) ! handle, error
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMsetFromOptions(thermal_grid,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMsetUp(thermal_grid,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMCreateGlobalVector(thermal_grid,solution_vec,err_PETSc) ! global solution vector (grid x 1, i.e. every def grad tensor)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMDASNESSetFunctionLocal(thermal_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,err_PETSc) ! residual vector of same shape as solution vector
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetDM(SNES_thermal,thermal_grid,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetFromOptions(SNES_thermal,err_PETSc) ! pull it all together with additional CLI arguments
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMDAVecGetArrayF90(thermal_grid,solution_vec,T_PETSc,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
T_PETSc = T_current
|
||||||
|
call DMDAVecRestoreArrayF90(thermal_grid,solution_vec,T_PETSc,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
call updateReference
|
call updateReference()
|
||||||
|
|
||||||
end subroutine grid_thermal_spectral_init
|
end subroutine grid_thermal_spectral_init
|
||||||
|
|
||||||
|
@ -164,7 +165,8 @@ function grid_thermal_spectral_solution(Delta_t) result(solution)
|
||||||
PetscInt :: devNull
|
PetscInt :: devNull
|
||||||
PetscReal :: T_min, T_max, stagNorm
|
PetscReal :: T_min, T_max, stagNorm
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
PetscErrorCode :: err_PETSc
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
|
|
||||||
solution%converged =.false.
|
solution%converged =.false.
|
||||||
|
@ -173,8 +175,10 @@ function grid_thermal_spectral_solution(Delta_t) result(solution)
|
||||||
! set module wide availabe data
|
! set module wide availabe data
|
||||||
params%Delta_t = Delta_t
|
params%Delta_t = Delta_t
|
||||||
|
|
||||||
call SNESSolve(thermal_snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr)
|
call SNESSolve(SNES_thermal,PETSC_NULL_VEC,solution_vec,err_PETSc)
|
||||||
call SNESGetConvergedReason(thermal_snes,reason,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESGetConvergedReason(SNES_thermal,reason,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
if (reason < 1) then
|
if (reason < 1) then
|
||||||
solution%converged = .false.
|
solution%converged = .false.
|
||||||
|
@ -184,9 +188,11 @@ function grid_thermal_spectral_solution(Delta_t) result(solution)
|
||||||
solution%iterationsNeeded = totalIter
|
solution%iterationsNeeded = totalIter
|
||||||
end if
|
end if
|
||||||
stagNorm = maxval(abs(T_current - T_stagInc))
|
stagNorm = maxval(abs(T_current - T_stagInc))
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,stagNorm,1,MPI_DOUBLE,MPI_MAX,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,stagNorm,1_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_MAX,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
solution%stagConverged = stagNorm < max(num%eps_thermal_atol, num%eps_thermal_rtol*maxval(T_current))
|
solution%stagConverged = stagNorm < max(num%eps_thermal_atol, num%eps_thermal_rtol*maxval(T_current))
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,solution%stagConverged,1,MPI_LOGICAL,MPI_LAND,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,solution%stagConverged,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LAND,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
T_stagInc = T_current
|
T_stagInc = T_current
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -197,8 +203,10 @@ function grid_thermal_spectral_solution(Delta_t) result(solution)
|
||||||
call homogenization_thermal_setField(T_current(i,j,k),(T_current(i,j,k)-T_lastInc(i,j,k))/params%Delta_t,ce)
|
call homogenization_thermal_setField(T_current(i,j,k),(T_current(i,j,k)-T_lastInc(i,j,k))/params%Delta_t,ce)
|
||||||
end do; end do; end do
|
end do; end do; end do
|
||||||
|
|
||||||
call VecMin(solution_vec,devNull,T_min,ierr); CHKERRQ(ierr)
|
call VecMin(solution_vec,devNull,T_min,err_PETSc)
|
||||||
call VecMax(solution_vec,devNull,T_max,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call VecMax(solution_vec,devNull,T_max,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
if (solution%converged) &
|
if (solution%converged) &
|
||||||
print'(/,1x,a)', '... thermal conduction converged ..................................'
|
print'(/,1x,a)', '... thermal conduction converged ..................................'
|
||||||
print'(/,1x,a,f8.4,2x,f8.4,2x,f8.4)', 'Minimum|Maximum|Delta Temperature / K = ', T_min, T_max, stagNorm
|
print'(/,1x,a,f8.4,2x,f8.4,2x,f8.4)', 'Minimum|Maximum|Delta Temperature / K = ', T_min, T_max, stagNorm
|
||||||
|
@ -216,8 +224,8 @@ subroutine grid_thermal_spectral_forward(cutBack)
|
||||||
logical, intent(in) :: cutBack
|
logical, intent(in) :: cutBack
|
||||||
integer :: i, j, k, ce
|
integer :: i, j, k, ce
|
||||||
DM :: dm_local
|
DM :: dm_local
|
||||||
PetscScalar, dimension(:,:,:), pointer :: x_scal
|
PetscScalar, dimension(:,:,:), pointer :: T_PETSc
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
if (cutBack) then
|
if (cutBack) then
|
||||||
T_current = T_lastInc
|
T_current = T_lastInc
|
||||||
|
@ -225,10 +233,13 @@ subroutine grid_thermal_spectral_forward(cutBack)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! reverting thermal field state
|
! reverting thermal field state
|
||||||
call SNESGetDM(thermal_snes,dm_local,ierr); CHKERRQ(ierr)
|
call SNESGetDM(SNES_thermal,dm_local,err_PETSc)
|
||||||
call DMDAVecGetArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with
|
CHKERRQ(err_PETSc)
|
||||||
x_scal(xstart:xend,ystart:yend,zstart:zend) = T_current
|
call DMDAVecGetArrayF90(dm_local,solution_vec,T_PETSc,err_PETSc) !< get the data out of PETSc to work with
|
||||||
call DMDAVecRestoreArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
T_PETSc = T_current
|
||||||
|
call DMDAVecRestoreArrayF90(dm_local,solution_vec,T_PETSc,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
ce = 0
|
ce = 0
|
||||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||||
ce = ce + 1
|
ce = ce + 1
|
||||||
|
@ -245,7 +256,7 @@ end subroutine grid_thermal_spectral_forward
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief forms the spectral thermal residual vector
|
!> @brief forms the spectral thermal residual vector
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
subroutine formResidual(in,x_scal,r,dummy,err_PETSc)
|
||||||
|
|
||||||
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
|
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
|
||||||
in
|
in
|
||||||
|
@ -254,9 +265,9 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
||||||
x_scal
|
x_scal
|
||||||
PetscScalar, dimension( &
|
PetscScalar, dimension( &
|
||||||
X_RANGE,Y_RANGE,Z_RANGE), intent(out) :: &
|
X_RANGE,Y_RANGE,Z_RANGE), intent(out) :: &
|
||||||
f_scal
|
r
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer :: i, j, k, ce
|
integer :: i, j, k, ce
|
||||||
|
|
||||||
T_current = x_scal
|
T_current = x_scal
|
||||||
|
@ -291,7 +302,8 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! constructing residual
|
! constructing residual
|
||||||
f_scal = T_current - scalarField_real(1:grid(1),1:grid(2),1:grid3)
|
r = T_current - scalarField_real(1:grid(1),1:grid(2),1:grid3)
|
||||||
|
err_PETSc = 0
|
||||||
|
|
||||||
end subroutine formResidual
|
end subroutine formResidual
|
||||||
|
|
||||||
|
@ -301,7 +313,8 @@ end subroutine formResidual
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine updateReference()
|
subroutine updateReference()
|
||||||
|
|
||||||
integer :: ce,ierr
|
integer :: ce
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
|
|
||||||
K_ref = 0.0_pReal
|
K_ref = 0.0_pReal
|
||||||
|
@ -312,9 +325,11 @@ subroutine updateReference()
|
||||||
end do
|
end do
|
||||||
|
|
||||||
K_ref = K_ref*wgt
|
K_ref = K_ref*wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
mu_ref = mu_ref*wgt
|
mu_ref = mu_ref*wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,mu_ref,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,mu_ref,1_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
end subroutine updateReference
|
end subroutine updateReference
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ contains
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine spectral_utilities_init
|
subroutine spectral_utilities_init
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer :: i, j, k, &
|
integer :: i, j, k, &
|
||||||
FFTW_planner_flag
|
FFTW_planner_flag
|
||||||
integer, dimension(3) :: k_s
|
integer, dimension(3) :: k_s
|
||||||
|
@ -156,7 +156,7 @@ subroutine spectral_utilities_init
|
||||||
integer(C_INTPTR_T) :: alloc_local, local_K, local_K_offset
|
integer(C_INTPTR_T) :: alloc_local, local_K, local_K_offset
|
||||||
integer(C_INTPTR_T), parameter :: &
|
integer(C_INTPTR_T), parameter :: &
|
||||||
scalarSize = 1_C_INTPTR_T, &
|
scalarSize = 1_C_INTPTR_T, &
|
||||||
vecSize = 3_C_INTPTR_T, &
|
vectorSize = 3_C_INTPTR_T, &
|
||||||
tensorSize = 9_C_INTPTR_T
|
tensorSize = 9_C_INTPTR_T
|
||||||
character(len=*), parameter :: &
|
character(len=*), parameter :: &
|
||||||
PETSCDEBUG = ' -snes_view -snes_monitor '
|
PETSCDEBUG = ' -snes_view -snes_monitor '
|
||||||
|
@ -193,13 +193,13 @@ subroutine spectral_utilities_init
|
||||||
'add more using the "PETSc_options" keyword in numerics.yaml'
|
'add more using the "PETSc_options" keyword in numerics.yaml'
|
||||||
flush(IO_STDOUT)
|
flush(IO_STDOUT)
|
||||||
|
|
||||||
call PetscOptionsClear(PETSC_NULL_OPTIONS,ierr)
|
call PetscOptionsClear(PETSC_NULL_OPTIONS,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
if (debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(PETSCDEBUG),ierr)
|
if (debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(PETSCDEBUG),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,&
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,&
|
||||||
num_grid%get_asString('PETSc_options',defaultVal=''),ierr)
|
num_grid%get_asString('PETSc_options',defaultVal=''),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
grid1Red = grid(1)/2 + 1
|
grid1Red = grid(1)/2 + 1
|
||||||
wgt = 1.0/real(product(grid),pReal)
|
wgt = 1.0/real(product(grid),pReal)
|
||||||
|
@ -274,7 +274,7 @@ subroutine spectral_utilities_init
|
||||||
call c_f_pointer(tensorField, tensorField_fourier, [3_C_INTPTR_T,3_C_INTPTR_T, &
|
call c_f_pointer(tensorField, tensorField_fourier, [3_C_INTPTR_T,3_C_INTPTR_T, &
|
||||||
gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T , gridFFTW(2),local_K]) ! place a pointer for a fourier tensor representation
|
gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T , gridFFTW(2),local_K]) ! place a pointer for a fourier tensor representation
|
||||||
|
|
||||||
vectorField = fftw_alloc_complex(vecSize*alloc_local)
|
vectorField = fftw_alloc_complex(vectorSize*alloc_local)
|
||||||
call c_f_pointer(vectorField, vectorField_real, [3_C_INTPTR_T,&
|
call c_f_pointer(vectorField, vectorField_real, [3_C_INTPTR_T,&
|
||||||
2_C_INTPTR_T*(gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T),gridFFTW(2),local_K]) ! place a pointer for a real vector representation
|
2_C_INTPTR_T*(gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T),gridFFTW(2),local_K]) ! place a pointer for a real vector representation
|
||||||
call c_f_pointer(vectorField, vectorField_fourier,[3_C_INTPTR_T,&
|
call c_f_pointer(vectorField, vectorField_fourier,[3_C_INTPTR_T,&
|
||||||
|
@ -288,42 +288,42 @@ subroutine spectral_utilities_init
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! tensor MPI fftw plans
|
! tensor MPI fftw plans
|
||||||
planTensorForth = fftw_mpi_plan_many_dft_r2c(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order
|
planTensorForth = fftw_mpi_plan_many_dft_r2c(3,gridFFTW(3:1:-1),tensorSize, &
|
||||||
tensorSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock
|
FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
|
||||||
tensorField_real, tensorField_fourier, & ! input data, output data
|
tensorField_real,tensorField_fourier, &
|
||||||
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision
|
PETSC_COMM_WORLD,FFTW_planner_flag)
|
||||||
if (.not. C_ASSOCIATED(planTensorForth)) error stop 'FFTW error'
|
if (.not. c_associated(planTensorForth)) error stop 'FFTW error'
|
||||||
planTensorBack = fftw_mpi_plan_many_dft_c2r(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order
|
planTensorBack = fftw_mpi_plan_many_dft_c2r(3,gridFFTW(3:1:-1),tensorSize, &
|
||||||
tensorSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock
|
FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &
|
||||||
tensorField_fourier,tensorField_real, & ! input data, output data
|
tensorField_fourier,tensorField_real, &
|
||||||
PETSC_COMM_WORLD, FFTW_planner_flag) ! all processors, planer precision
|
PETSC_COMM_WORLD, FFTW_planner_flag)
|
||||||
if (.not. C_ASSOCIATED(planTensorBack)) error stop 'FFTW error'
|
if (.not. c_associated(planTensorBack)) error stop 'FFTW error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! vector MPI fftw plans
|
! vector MPI fftw plans
|
||||||
planVectorForth = fftw_mpi_plan_many_dft_r2c(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order
|
planVectorForth = fftw_mpi_plan_many_dft_r2c(3,gridFFTW(3:1:-1),vectorSize, &
|
||||||
vecSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,&! no. of transforms, default iblock and oblock
|
FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
|
||||||
vectorField_real, vectorField_fourier, & ! input data, output data
|
vectorField_real,vectorField_fourier, &
|
||||||
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision
|
PETSC_COMM_WORLD,FFTW_planner_flag)
|
||||||
if (.not. C_ASSOCIATED(planVectorForth)) error stop 'FFTW error'
|
if (.not. c_associated(planVectorForth)) error stop 'FFTW error'
|
||||||
planVectorBack = fftw_mpi_plan_many_dft_c2r(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order
|
planVectorBack = fftw_mpi_plan_many_dft_c2r(3,gridFFTW(3:1:-1),vectorSize, &
|
||||||
vecSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, & ! no. of transforms, default iblock and oblock
|
FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &
|
||||||
vectorField_fourier,vectorField_real, & ! input data, output data
|
vectorField_fourier,vectorField_real, &
|
||||||
PETSC_COMM_WORLD, FFTW_planner_flag) ! all processors, planer precision
|
PETSC_COMM_WORLD, FFTW_planner_flag)
|
||||||
if (.not. C_ASSOCIATED(planVectorBack)) error stop 'FFTW error'
|
if (.not. c_associated(planVectorBack)) error stop 'FFTW error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! scalar MPI fftw plans
|
! scalar MPI fftw plans
|
||||||
planScalarForth = fftw_mpi_plan_many_dft_r2c(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order
|
planScalarForth = fftw_mpi_plan_many_dft_r2c(3,gridFFTW(3:1:-1),scalarSize, &
|
||||||
scalarSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock
|
FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
|
||||||
scalarField_real, scalarField_fourier, & ! input data, output data
|
scalarField_real,scalarField_fourier, &
|
||||||
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision
|
PETSC_COMM_WORLD,FFTW_planner_flag)
|
||||||
if (.not. C_ASSOCIATED(planScalarForth)) error stop 'FFTW error'
|
if (.not. c_associated(planScalarForth)) error stop 'FFTW error'
|
||||||
planScalarBack = fftw_mpi_plan_many_dft_c2r(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order, no. of transforms
|
planScalarBack = fftw_mpi_plan_many_dft_c2r(3,gridFFTW(3:1:-1),scalarSize, &
|
||||||
scalarSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock
|
FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &
|
||||||
scalarField_fourier,scalarField_real, & ! input data, output data
|
scalarField_fourier,scalarField_real, &
|
||||||
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision
|
PETSC_COMM_WORLD, FFTW_planner_flag)
|
||||||
if (.not. C_ASSOCIATED(planScalarBack)) error stop 'FFTW error'
|
if (.not. c_associated(planScalarBack)) error stop 'FFTW error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! calculation of discrete angular frequencies, ordered as in FFTW (wrap around)
|
! calculation of discrete angular frequencies, ordered as in FFTW (wrap around)
|
||||||
|
@ -559,7 +559,8 @@ end subroutine utilities_fourierGreenConvolution
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
real(pReal) function utilities_divergenceRMS()
|
real(pReal) function utilities_divergenceRMS()
|
||||||
|
|
||||||
integer :: i, j, k, ierr
|
integer :: i, j, k
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
complex(pReal), dimension(3) :: rescaledGeom
|
complex(pReal), dimension(3) :: rescaledGeom
|
||||||
|
|
||||||
print'(/,1x,a)', '... calculating divergence ................................................'
|
print'(/,1x,a)', '... calculating divergence ................................................'
|
||||||
|
@ -589,8 +590,8 @@ real(pReal) function utilities_divergenceRMS()
|
||||||
conjg(-xi1st(1:3,grid1Red,j,k))*rescaledGeom))**2)
|
conjg(-xi1st(1:3,grid1Red,j,k))*rescaledGeom))**2)
|
||||||
enddo; enddo
|
enddo; enddo
|
||||||
if (grid(1) == 1) utilities_divergenceRMS = utilities_divergenceRMS * 0.5_pReal ! counted twice in case of grid(1) == 1
|
if (grid(1) == 1) utilities_divergenceRMS = utilities_divergenceRMS * 0.5_pReal ! counted twice in case of grid(1) == 1
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,utilities_divergenceRMS,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,utilities_divergenceRMS,1_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
utilities_divergenceRMS = sqrt(utilities_divergenceRMS) * wgt ! RMS in real space calculated with Parsevals theorem from Fourier space
|
utilities_divergenceRMS = sqrt(utilities_divergenceRMS) * wgt ! RMS in real space calculated with Parsevals theorem from Fourier space
|
||||||
|
|
||||||
end function utilities_divergenceRMS
|
end function utilities_divergenceRMS
|
||||||
|
@ -601,7 +602,8 @@ end function utilities_divergenceRMS
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
real(pReal) function utilities_curlRMS()
|
real(pReal) function utilities_curlRMS()
|
||||||
|
|
||||||
integer :: i, j, k, l, ierr
|
integer :: i, j, k, l
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
complex(pReal), dimension(3,3) :: curl_fourier
|
complex(pReal), dimension(3,3) :: curl_fourier
|
||||||
complex(pReal), dimension(3) :: rescaledGeom
|
complex(pReal), dimension(3) :: rescaledGeom
|
||||||
|
|
||||||
|
@ -649,8 +651,8 @@ real(pReal) function utilities_curlRMS()
|
||||||
+ sum(curl_fourier%re**2 + curl_fourier%im**2) ! this layer (Nyquist) does not have a conjugate complex counterpart (if grid(1) /= 1)
|
+ sum(curl_fourier%re**2 + curl_fourier%im**2) ! this layer (Nyquist) does not have a conjugate complex counterpart (if grid(1) /= 1)
|
||||||
enddo; enddo
|
enddo; enddo
|
||||||
|
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,utilities_curlRMS,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,utilities_curlRMS,1_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
utilities_curlRMS = sqrt(utilities_curlRMS) * wgt
|
utilities_curlRMS = sqrt(utilities_curlRMS) * wgt
|
||||||
if (grid(1) == 1) utilities_curlRMS = utilities_curlRMS * 0.5_pReal ! counted twice in case of grid(1) == 1
|
if (grid(1) == 1) utilities_curlRMS = utilities_curlRMS * 0.5_pReal ! counted twice in case of grid(1) == 1
|
||||||
|
|
||||||
|
@ -799,8 +801,8 @@ subroutine utilities_constitutiveResponse(P,P_av,C_volAvg,C_minmaxAvg,&
|
||||||
type(rotation), intent(in), optional :: rotation_BC !< rotation of load frame
|
type(rotation), intent(in), optional :: rotation_BC !< rotation of load frame
|
||||||
|
|
||||||
|
|
||||||
integer :: &
|
integer :: i
|
||||||
i,ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
real(pReal), dimension(3,3,3,3) :: dPdF_max, dPdF_min
|
real(pReal), dimension(3,3,3,3) :: dPdF_max, dPdF_min
|
||||||
real(pReal) :: dPdF_norm_max, dPdF_norm_min
|
real(pReal) :: dPdF_norm_max, dPdF_norm_min
|
||||||
real(pReal), dimension(2) :: valueAndRank !< pair of min/max norm of dPdF to synchronize min/max of dPdF
|
real(pReal), dimension(2) :: valueAndRank !< pair of min/max norm of dPdF to synchronize min/max of dPdF
|
||||||
|
@ -818,7 +820,8 @@ subroutine utilities_constitutiveResponse(P,P_av,C_volAvg,C_minmaxAvg,&
|
||||||
|
|
||||||
P = reshape(homogenization_P, [3,3,grid(1),grid(2),grid3])
|
P = reshape(homogenization_P, [3,3,grid(1),grid(2),grid3])
|
||||||
P_av = sum(sum(sum(P,dim=5),dim=4),dim=3) * wgt
|
P_av = sum(sum(sum(P,dim=5),dim=4),dim=3) * wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,P_av,9,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,P_av,9_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
if (debugRotation) print'(/,1x,a,/,2(3(2x,f12.4,1x)/),3(2x,f12.4,1x))', &
|
if (debugRotation) print'(/,1x,a,/,2(3(2x,f12.4,1x)/),3(2x,f12.4,1x))', &
|
||||||
'Piola--Kirchhoff stress (lab) / MPa =', transpose(P_av)*1.e-6_pReal
|
'Piola--Kirchhoff stress (lab) / MPa =', transpose(P_av)*1.e-6_pReal
|
||||||
if (present(rotation_BC)) P_av = rotation_BC%rotate(P_av)
|
if (present(rotation_BC)) P_av = rotation_BC%rotate(P_av)
|
||||||
|
@ -842,22 +845,22 @@ subroutine utilities_constitutiveResponse(P,P_av,C_volAvg,C_minmaxAvg,&
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
valueAndRank = [dPdF_norm_max,real(worldrank,pReal)]
|
valueAndRank = [dPdF_norm_max,real(worldrank,pReal)]
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,valueAndRank,1, MPI_2DOUBLE_PRECISION, MPI_MAXLOC, MPI_COMM_WORLD, ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,valueAndRank,1_MPI_INTEGER_KIND,MPI_2DOUBLE_PRECISION,MPI_MAXLOC,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call MPI_Bcast(dPdF_max,81,MPI_DOUBLE,int(valueAndRank(2)),MPI_COMM_WORLD, ierr)
|
call MPI_Bcast(dPdF_max,81_MPI_INTEGER_KIND,MPI_DOUBLE,int(valueAndRank(2),MPI_INTEGER_KIND),MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
valueAndRank = [dPdF_norm_min,real(worldrank,pReal)]
|
valueAndRank = [dPdF_norm_min,real(worldrank,pReal)]
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,valueAndRank,1, MPI_2DOUBLE_PRECISION, MPI_MINLOC, MPI_COMM_WORLD, ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,valueAndRank,1_MPI_INTEGER_KIND,MPI_2DOUBLE_PRECISION,MPI_MINLOC,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call MPI_Bcast(dPdF_min,81,MPI_DOUBLE,int(valueAndRank(2)),MPI_COMM_WORLD, ierr)
|
call MPI_Bcast(dPdF_min,81_MPI_INTEGER_KIND,MPI_DOUBLE,int(valueAndRank(2),MPI_INTEGER_KIND),MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
C_minmaxAvg = 0.5_pReal*(dPdF_max + dPdF_min)
|
C_minmaxAvg = 0.5_pReal*(dPdF_max + dPdF_min)
|
||||||
|
|
||||||
C_volAvg = sum(homogenization_dPdF,dim=5)
|
C_volAvg = sum(homogenization_dPdF,dim=5)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,C_volAvg,81,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,C_volAvg,81_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /= 0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
C_volAvg = C_volAvg * wgt
|
C_volAvg = C_volAvg * wgt
|
||||||
|
|
||||||
|
|
||||||
|
@ -906,12 +909,13 @@ function utilities_forwardField(Delta_t,field_lastInc,rate,aim)
|
||||||
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: &
|
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: &
|
||||||
utilities_forwardField
|
utilities_forwardField
|
||||||
real(pReal), dimension(3,3) :: fieldDiff !< <a + adot*t> - aim
|
real(pReal), dimension(3,3) :: fieldDiff !< <a + adot*t> - aim
|
||||||
PetscErrorCode :: ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
utilities_forwardField = field_lastInc + rate*Delta_t
|
utilities_forwardField = field_lastInc + rate*Delta_t
|
||||||
if (present(aim)) then !< correct to match average
|
if (present(aim)) then !< correct to match average
|
||||||
fieldDiff = sum(sum(sum(utilities_forwardField,dim=5),dim=4),dim=3)*wgt
|
fieldDiff = sum(sum(sum(utilities_forwardField,dim=5),dim=4),dim=3)*wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,fieldDiff,9,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,fieldDiff,9_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
fieldDiff = fieldDiff - aim
|
fieldDiff = fieldDiff - aim
|
||||||
utilities_forwardField = utilities_forwardField - &
|
utilities_forwardField = utilities_forwardField - &
|
||||||
spread(spread(spread(fieldDiff,3,grid(1)),4,grid(2)),5,grid3)
|
spread(spread(spread(fieldDiff,3,grid(1)),4,grid(2)),5,grid3)
|
||||||
|
@ -981,9 +985,10 @@ subroutine utilities_updateCoords(F)
|
||||||
real(pReal), dimension(3, grid(1)+1,grid(2)+1,grid3+1) :: nodeCoords
|
real(pReal), dimension(3, grid(1)+1,grid(2)+1,grid3+1) :: nodeCoords
|
||||||
integer :: &
|
integer :: &
|
||||||
i,j,k,n, &
|
i,j,k,n, &
|
||||||
rank_t, rank_b, &
|
c
|
||||||
c, &
|
integer(MPI_INTEGER_KIND) :: &
|
||||||
ierr
|
rank_t, rank_b
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
#if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY)
|
#if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY)
|
||||||
type(MPI_Request), dimension(4) :: request
|
type(MPI_Request), dimension(4) :: request
|
||||||
type(MPI_Status), dimension(4) :: status
|
type(MPI_Status), dimension(4) :: status
|
||||||
|
@ -1025,30 +1030,30 @@ subroutine utilities_updateCoords(F)
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! average F
|
! average F
|
||||||
if (grid3Offset == 0) Favg = real(tensorField_fourier(1:3,1:3,1,1,1),pReal)*wgt
|
if (grid3Offset == 0) Favg = real(tensorField_fourier(1:3,1:3,1,1,1),pReal)*wgt
|
||||||
call MPI_Bcast(Favg,9,MPI_DOUBLE,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(Favg,9_MPI_INTEGER_KIND,MPI_DOUBLE,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! pad cell center fluctuations along z-direction (needed when running MPI simulation)
|
! pad cell center fluctuations along z-direction (needed when running MPI simulation)
|
||||||
IPfluct_padded(1:3,1:grid(1),1:grid(2),2:grid3+1) = vectorField_real(1:3,1:grid(1),1:grid(2),1:grid3)
|
IPfluct_padded(1:3,1:grid(1),1:grid(2),2:grid3+1) = vectorField_real(1:3,1:grid(1),1:grid(2),1:grid3)
|
||||||
c = product(shape(IPfluct_padded(:,:,:,1))) !< amount of data to transfer
|
c = product(shape(IPfluct_padded(:,:,:,1))) !< amount of data to transfer
|
||||||
rank_t = modulo(worldrank+1,worldsize)
|
rank_t = modulo(worldrank+1_MPI_INTEGER_KIND,worldsize)
|
||||||
rank_b = modulo(worldrank-1,worldsize)
|
rank_b = modulo(worldrank-1_MPI_INTEGER_KIND,worldsize)
|
||||||
|
|
||||||
! send bottom layer to process below
|
! send bottom layer to process below
|
||||||
call MPI_Isend(IPfluct_padded(:,:,:,2), c,MPI_DOUBLE,rank_b,0,MPI_COMM_WORLD,request(1),ierr)
|
call MPI_Isend(IPfluct_padded(:,:,:,2), c,MPI_DOUBLE,rank_b,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(1),err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call MPI_Irecv(IPfluct_padded(:,:,:,grid3+2),c,MPI_DOUBLE,rank_t,0,MPI_COMM_WORLD,request(2),ierr)
|
call MPI_Irecv(IPfluct_padded(:,:,:,grid3+2),c,MPI_DOUBLE,rank_t,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(2),err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
! send top layer to process above
|
! send top layer to process above
|
||||||
call MPI_Isend(IPfluct_padded(:,:,:,grid3+1),c,MPI_DOUBLE,rank_t,1,MPI_COMM_WORLD,request(3),ierr)
|
call MPI_Isend(IPfluct_padded(:,:,:,grid3+1),c,MPI_DOUBLE,rank_t,1_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(3),err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
call MPI_Irecv(IPfluct_padded(:,:,:,1), c,MPI_DOUBLE,rank_b,1,MPI_COMM_WORLD,request(4),ierr)
|
call MPI_Irecv(IPfluct_padded(:,:,:,1), c,MPI_DOUBLE,rank_b,1_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(4),err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
call MPI_Waitall(4,request,status,ierr)
|
call MPI_Waitall(4,request,status,err_MPI)
|
||||||
if (ierr /=0) error stop 'MPI error'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
#if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY)
|
#if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY)
|
||||||
! ToDo
|
! ToDo
|
||||||
#else
|
#else
|
||||||
|
|
142
src/lattice.f90
142
src/lattice.f90
|
@ -587,8 +587,8 @@ function lattice_C66_trans(Ntrans,C_parent66,lattice_target, &
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief Non-schmid projections for bcc with up to 6 coefficients
|
!> @brief Non-schmid projections for bcc with up to 6 coefficients
|
||||||
! Koester et al. 2012, Acta Materialia 60 (2012) 3894–3901, eq. (17)
|
! https://doi.org/10.1016/j.actamat.2012.03.053, eq. (17)
|
||||||
! Gröger et al. 2008, Acta Materialia 56 (2008) 5412–5425, table 1
|
! https://doi.org/10.1016/j.actamat.2008.07.037, table 1
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function lattice_nonSchmidMatrix(Nslip,nonSchmidCoefficients,sense) result(nonSchmidMatrix)
|
function lattice_nonSchmidMatrix(Nslip,nonSchmidCoefficients,sense) result(nonSchmidMatrix)
|
||||||
|
|
||||||
|
@ -602,6 +602,7 @@ function lattice_nonSchmidMatrix(Nslip,nonSchmidCoefficients,sense) result(nonSc
|
||||||
type(rotation) :: R
|
type(rotation) :: R
|
||||||
integer :: i
|
integer :: i
|
||||||
|
|
||||||
|
|
||||||
if (abs(sense) /= 1) error stop 'Sense in lattice_nonSchmidMatrix'
|
if (abs(sense) /= 1) error stop 'Sense in lattice_nonSchmidMatrix'
|
||||||
|
|
||||||
coordinateSystem = buildCoordinateSystem(Nslip,BCC_NSLIPSYSTEM,BCC_SYSTEMSLIP,'cI',0.0_pReal)
|
coordinateSystem = buildCoordinateSystem(Nslip,BCC_NSLIPSYSTEM,BCC_SYSTEMSLIP,'cI',0.0_pReal)
|
||||||
|
@ -634,7 +635,9 @@ end function lattice_nonSchmidMatrix
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief Slip-slip interaction matrix
|
!> @brief Slip-slip interaction matrix
|
||||||
!> details only active slip systems are considered
|
!> @details only active slip systems are considered
|
||||||
|
!> @details https://doi.org/10.1016/j.actamat.2016.12.040 (fcc: Tab S4-1, bcc: Tab S5-1)
|
||||||
|
!> @details https://doi.org/10.1016/j.ijplas.2014.06.010 (hex: Tab 3b)
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(interactionMatrix)
|
function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(interactionMatrix)
|
||||||
|
|
||||||
|
@ -646,6 +649,7 @@ function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(
|
||||||
integer, dimension(:), allocatable :: NslipMax
|
integer, dimension(:), allocatable :: NslipMax
|
||||||
integer, dimension(:,:), allocatable :: interactionTypes
|
integer, dimension(:,:), allocatable :: interactionTypes
|
||||||
|
|
||||||
|
|
||||||
integer, dimension(FCC_NSLIP,FCC_NSLIP), parameter :: &
|
integer, dimension(FCC_NSLIP,FCC_NSLIP), parameter :: &
|
||||||
FCC_INTERACTIONSLIPSLIP = reshape( [&
|
FCC_INTERACTIONSLIPSLIP = reshape( [&
|
||||||
1, 2, 2, 4, 7, 5, 3, 5, 5, 4, 6, 7, 10,11,10,11,12,13, & ! -----> acting (forest)
|
1, 2, 2, 4, 7, 5, 3, 5, 5, 4, 6, 7, 10,11,10,11,12,13, & ! -----> acting (forest)
|
||||||
|
@ -750,41 +754,113 @@ function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(
|
||||||
integer, dimension(HEX_NSLIP,HEX_NSLIP), parameter :: &
|
integer, dimension(HEX_NSLIP,HEX_NSLIP), parameter :: &
|
||||||
HEX_INTERACTIONSLIPSLIP = reshape( [&
|
HEX_INTERACTIONSLIPSLIP = reshape( [&
|
||||||
! basal prism 1. pyr<a> 1. pyr<c+a> 2. pyr<c+a>
|
! basal prism 1. pyr<a> 1. pyr<c+a> 2. pyr<c+a>
|
||||||
1, 2, 2, 3, 3, 3, 7, 7, 7, 7, 7, 7, 13,13,13,13,13,13,13,13,13,13,13,13, 21,21,21,21,21,21, & ! -----> acting (forest)
|
1, 2, 2, 3, 4, 4, 9,10, 9, 9,10, 9, 20,21,22,22,21,20,20,21,22,22,21,20, 47,47,48,47,47,48, & ! -----> acting (forest)
|
||||||
2, 1, 2, 3, 3, 3, 7, 7, 7, 7, 7, 7, 13,13,13,13,13,13,13,13,13,13,13,13, 21,21,21,21,21,21, & ! | basal
|
2, 1, 2, 4, 3, 4, 10, 9, 9,10, 9, 9, 22,22,21,20,20,21,22,22,21,20,20,21, 47,48,47,47,48,47, & ! | basal
|
||||||
2, 2, 1, 3, 3, 3, 7, 7, 7, 7, 7, 7, 13,13,13,13,13,13,13,13,13,13,13,13, 21,21,21,21,21,21, & ! |
|
2, 2, 1, 4, 4, 3, 9, 9,10, 9, 9,10, 21,20,20,21,22,22,21,20,20,21,22,22, 48,47,47,48,47,47, & ! |
|
||||||
! v
|
! v
|
||||||
6, 6, 6, 4, 5, 5, 8, 8, 8, 8, 8, 8, 14,14,14,14,14,14,14,14,14,14,14,14, 22,22,22,22,22,22, & ! reacting (primary)
|
7, 8, 8, 5, 6, 6, 11,12,11,11,12,11, 23,24,25,25,24,23,23,24,25,25,24,23, 49,49,50,49,49,50, & ! reacting (primary)
|
||||||
6, 6, 6, 5, 4, 5, 8, 8, 8, 8, 8, 8, 14,14,14,14,14,14,14,14,14,14,14,14, 22,22,22,22,22,22, & ! prism
|
8, 7, 8, 6, 5, 6, 12,11,11,12,11,11, 25,25,24,23,23,24,25,25,24,23,23,24, 49,50,49,49,50,49, & ! prism
|
||||||
6, 6, 6, 5, 5, 4, 8, 8, 8, 8, 8, 8, 14,14,14,14,14,14,14,14,14,14,14,14, 22,22,22,22,22,22, &
|
8, 8, 7, 6, 6, 5, 11,11,12,11,11,12, 24,23,23,24,25,25,24,23,23,24,25,25, 50,49,49,50,49,49, &
|
||||||
|
|
||||||
12,12,12, 11,11,11, 9,10,10,10,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, &
|
18,19,18, 16,17,16, 13,14,14,15,14,14, 26,26,27,28,28,27,29,29,27,28,28,27, 51,52,51,51,52,51, &
|
||||||
12,12,12, 11,11,11, 10, 9,10,10,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, &
|
19,18,18, 17,16,16, 14,13,14,14,15,14, 28,27,26,26,27,28,28,27,29,29,27,28, 51,51,52,51,51,52, &
|
||||||
12,12,12, 11,11,11, 10,10, 9,10,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, &
|
18,18,19, 16,16,17, 14,14,13,14,14,15, 27,28,28,27,26,26,27,28,28,27,29,29, 52,51,51,52,51,51, &
|
||||||
12,12,12, 11,11,11, 10,10,10, 9,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, & ! 1. pyr<a>
|
18,19,18, 16,17,16, 15,14,14,13,14,14, 29,29,27,28,28,27,26,26,27,28,28,27, 51,52,51,51,52,51, & ! 1. pyr<a>
|
||||||
12,12,12, 11,11,11, 10,10,10,10, 9,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, &
|
19,18,18, 17,16,16, 14,15,14,14,13,14, 28,27,29,29,27,28,28,27,26,26,27,28, 51,51,52,51,51,52, &
|
||||||
12,12,12, 11,11,11, 10,10,10,10,10, 9, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, &
|
18,18,19, 16,16,17, 14,14,15,14,14,13, 27,28,28,27,29,29,27,28,28,27,26,26, 52,51,51,52,51,51, &
|
||||||
|
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 16,17,17,17,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, &
|
44,45,46, 41,42,43, 37,38,39,40,38,39, 30,31,32,32,32,33,34,35,32,32,32,36, 53,54,55,53,54,56, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,16,17,17,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, &
|
46,45,44, 43,42,41, 37,39,38,40,39,38, 31,30,36,32,32,32,35,34,33,32,32,32, 56,54,53,55,54,53, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,16,17,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, &
|
45,46,44, 42,43,41, 39,37,38,39,40,38, 32,36,30,31,32,32,32,33,34,35,32,32, 56,53,54,55,53,54, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,16,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, &
|
45,44,46, 42,41,43, 38,37,39,38,40,39, 32,32,31,30,36,32,32,32,35,34,33,32, 53,56,54,53,55,54, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,16,17,17,17,17,17,17,17, 24,24,24,24,24,24, &
|
46,44,45, 43,41,42, 38,39,37,38,39,40, 32,32,32,36,30,31,32,32,32,33,34,35, 54,56,53,54,55,53, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,16,17,17,17,17,17,17, 24,24,24,24,24,24, &
|
44,46,45, 41,43,42, 39,38,37,39,38,40, 33,32,32,32,31,30,36,32,32,32,35,34, 54,53,56,54,53,55, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,16,17,17,17,17,17, 24,24,24,24,24,24, & ! 1. pyr<c+a>
|
44,45,46, 41,42,43, 40,38,39,37,38,39, 34,35,32,32,32,36,30,31,32,32,32,33, 53,54,56,53,54,55, & ! 1. pyr<c+a>
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,16,17,17,17,17, 24,24,24,24,24,24, &
|
46,45,44, 43,42,41, 40,39,38,37,39,38, 35,34,33,32,32,32,31,30,36,32,32,32, 55,54,53,56,54,53, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,16,17,17,17, 24,24,24,24,24,24, &
|
45,46,44, 42,43,41, 39,40,38,39,37,38, 32,33,34,35,32,32,32,36,30,31,32,32, 55,53,54,56,53,54, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,17,16,17,17, 24,24,24,24,24,24, &
|
45,44,46, 42,41,43, 38,40,39,38,37,39, 32,32,35,34,33,32,32,32,31,30,36,32, 53,55,54,53,56,54, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,17,17,16,17, 24,24,24,24,24,24, &
|
46,44,45, 43,41,42, 38,39,40,38,39,37, 32,32,32,33,34,35,32,32,32,36,30,31, 54,55,53,54,56,53, &
|
||||||
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,17,17,17,16, 24,24,24,24,24,24, &
|
44,46,45, 41,43,42, 39,38,40,39,38,37, 36,32,32,32,35,34,33,32,32,32,31,30, 54,53,55,54,53,56, &
|
||||||
|
|
||||||
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 25,26,26,26,26,26, &
|
68,68,69, 66,66,67, 64,64,65,64,65,65, 60,61,61,60,62,62,60,63,63,60,62,62, 57,58,58,59,58,58, &
|
||||||
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,25,26,26,26,26, &
|
68,69,68, 66,67,66, 65,64,64,65,64,64, 62,62,60,61,61,60,62,62,60,63,63,60, 58,57,58,58,59,58, &
|
||||||
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,25,26,26,26, &
|
69,68,68, 67,66,66, 64,65,64,64,65,64, 63,60,62,62,60,61,61,60,62,62,60,63, 58,58,57,58,58,59, &
|
||||||
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,26,25,26,26, & ! 2. pyr<c+a>
|
68,68,69, 66,66,67, 64,64,65,64,64,65, 60,63,63,60,62,62,60,61,61,60,62,62, 59,58,58,57,58,58, & ! 2. pyr<c+a>
|
||||||
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,26,26,25,26, &
|
68,69,68, 66,67,66, 65,64,64,65,64,64, 62,62,60,63,63,60,62,62,60,61,61,60, 58,59,58,58,57,58, &
|
||||||
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,26,26,26,25 &
|
69,68,68, 67,66,66, 64,65,64,64,65,64, 61,60,62,62,60,63,63,60,62,62,60,61, 58,58,59,58,58,57 &
|
||||||
],shape(HEX_INTERACTIONSLIPSLIP)) !< Slip-slip interaction types for hex (onion peel naming scheme)
|
],shape(HEX_INTERACTIONSLIPSLIP)) !< Slip-slip interaction types for hex (onion peel naming scheme)
|
||||||
|
!< 10.1016/j.ijplas.2014.06.010 table 3
|
||||||
|
!< 10.1080/14786435.2012.699689 table 2 and 3
|
||||||
|
!< index & label & description
|
||||||
|
!< 1 & S1 & basal self-interaction
|
||||||
|
!< 2 & 1 & basal/basal coplanar
|
||||||
|
!< 3 & 3 & basal/prismatic collinear
|
||||||
|
!< 4 & 4 & basal/prismatic non-collinear
|
||||||
|
!< 5 & S2 & prismatic self-interaction
|
||||||
|
!< 6 & 2 & prismatic/prismatic
|
||||||
|
!< 7 & 5 & prismatic/basal collinear
|
||||||
|
!< 8 & 6 & prismatic/basal non-collinear
|
||||||
|
!< 9 & - & basal/pyramidal <a> non-collinear
|
||||||
|
!< 10 & - & basal/pyramidal <a> collinear
|
||||||
|
!< 11 & - & prismatic/pyramidal <a> non-collinear
|
||||||
|
!< 12 & - & prismatic/pyramidal <a> collinear
|
||||||
|
!< 13 & - & pyramidal <a> self-interaction
|
||||||
|
!< 14 & - & pyramidal <a> non-collinear
|
||||||
|
!< 15 & - & pyramidal <a> collinear
|
||||||
|
!< 16 & - & pyramidal <a>/prismatic non-collinear
|
||||||
|
!< 17 & - & pyramidal <a>/prismatic collinear
|
||||||
|
!< 18 & - & pyramidal <a>/basal non-collinear
|
||||||
|
!< 19 & - & pyramidal <a>/basal collinear
|
||||||
|
!< 20 & - & basal/1. order pyramidal <c+a> semi-collinear
|
||||||
|
!< 21 & - & basal/1. order pyramidal <c+a>
|
||||||
|
!< 22 & - & basal/1. order pyramidal <c+a>
|
||||||
|
!< 23 & - & prismatic/1. order pyramidal <c+a> semi-collinear
|
||||||
|
!< 24 & - & prismatic/1. order pyramidal <c+a>
|
||||||
|
!< 25 & - & prismatic/1. order pyramidal <c+a> semi-coplanar?
|
||||||
|
!< 26 & - & pyramidal <a>/1. order pyramidal <c+a> coplanar
|
||||||
|
!< 27 & - & pyramidal <a>/1. order pyramidal <c+a>
|
||||||
|
!< 28 & - & pyramidal <a>/1. order pyramidal <c+a> semi-collinear
|
||||||
|
!< 29 & - & pyramidal <a>/1. order pyramidal <c+a> semi-coplanar
|
||||||
|
!< 30 & - & 1. order pyramidal <c+a> self-interaction
|
||||||
|
!< 31 & - & 1. order pyramidal <c+a> coplanar
|
||||||
|
!< 32 & - & 1. order pyramidal <c+a>
|
||||||
|
!< 33 & - & 1. order pyramidal <c+a>
|
||||||
|
!< 34 & - & 1. order pyramidal <c+a> semi-coplanar
|
||||||
|
!< 35 & - & 1. order pyramidal <c+a> semi-coplanar
|
||||||
|
!< 36 & - & 1. order pyramidal <c+a> collinear
|
||||||
|
!< 37 & - & 1. order pyramidal <c+a>/pyramidal <a> coplanar
|
||||||
|
!< 38 & - & 1. order pyramidal <c+a>/pyramidal <a> semi-collinear
|
||||||
|
!< 39 & - & 1. order pyramidal <c+a>/pyramidal <a>
|
||||||
|
!< 40 & - & 1. order pyramidal <c+a>/pyramidal <a> semi-coplanar
|
||||||
|
!< 41 & - & 1. order pyramidal <c+a>/prismatic semi-collinear
|
||||||
|
!< 42 & - & 1. order pyramidal <c+a>/prismatic semi-coplanar
|
||||||
|
!< 43 & - & 1. order pyramidal <c+a>/prismatic
|
||||||
|
!< 44 & - & 1. order pyramidal <c+a>/basal semi-collinear
|
||||||
|
!< 45 & - & 1. order pyramidal <c+a>/basal
|
||||||
|
!< 46 & - & 1. order pyramidal <c+a>/basal
|
||||||
|
!< 47 & 8 & basal/2. order pyramidal <c+a> non-collinear
|
||||||
|
!< 48 & 7 & basal/2. order pyramidal <c+a> semi-collinear
|
||||||
|
!< 49 & 10 & prismatic/2. order pyramidal <c+a>
|
||||||
|
!< 50 & 9 & prismatic/2. order pyramidal <c+a> semi-collinear
|
||||||
|
!< 51 & - & pyramidal <a>/2. order pyramidal <c+a>
|
||||||
|
!< 52 & - & pyramidal <a>/2. order pyramidal <c+a> semi collinear
|
||||||
|
!< 53 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a>
|
||||||
|
!< 54 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a>
|
||||||
|
!< 55 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a>
|
||||||
|
!< 56 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a> collinear
|
||||||
|
!< 57 & S3 & 2. order pyramidal <c+a> self-interaction
|
||||||
|
!< 58 & 16 & 2. order pyramidal <c+a> non-collinear
|
||||||
|
!< 59 & 15 & 2. order pyramidal <c+a> semi-collinear
|
||||||
|
!< 60 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a>
|
||||||
|
!< 61 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a> collinear
|
||||||
|
!< 62 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a>
|
||||||
|
!< 63 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a>
|
||||||
|
!< 64 & - & 2. order pyramidal <c+a>/pyramidal <a> non-collinear
|
||||||
|
!< 65 & - & 2. order pyramidal <c+a>/pyramidal <a> semi-collinear
|
||||||
|
!< 66 & 14 & 2. order pyramidal <c+a>/prismatic non-collinear
|
||||||
|
!< 67 & 13 & 2. order pyramidal <c+a>/prismatic semi-collinear
|
||||||
|
!< 68 & 12 & 2. order pyramidal <c+a>/basal non-collinear
|
||||||
|
!< 69 & 11 & 2. order pyramidal <c+a>/basal semi-collinear
|
||||||
|
|
||||||
integer, dimension(BCT_NSLIP,BCT_NSLIP), parameter :: &
|
integer, dimension(BCT_NSLIP,BCT_NSLIP), parameter :: &
|
||||||
BCT_INTERACTIONSLIPSLIP = reshape( [&
|
BCT_INTERACTIONSLIPSLIP = reshape( [&
|
||||||
|
|
|
@ -66,7 +66,7 @@ subroutine material_init(restart)
|
||||||
print'(/,1x,a)', '<<<+- material init -+>>>'; flush(IO_STDOUT)
|
print'(/,1x,a)', '<<<+- material init -+>>>'; flush(IO_STDOUT)
|
||||||
|
|
||||||
|
|
||||||
call parse
|
call parse()
|
||||||
print'(/,1x,a)', 'parsed material.yaml'
|
print'(/,1x,a)', 'parsed material.yaml'
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,8 +108,14 @@ subroutine parse()
|
||||||
homogenizations => config_material%get('homogenization')
|
homogenizations => config_material%get('homogenization')
|
||||||
|
|
||||||
call sanityCheck(materials, homogenizations)
|
call sanityCheck(materials, homogenizations)
|
||||||
|
|
||||||
|
#if defined (__GFORTRAN__)
|
||||||
material_name_phase = getKeys(phases)
|
material_name_phase = getKeys(phases)
|
||||||
material_name_homogenization = getKeys(homogenizations)
|
material_name_homogenization = getKeys(homogenizations)
|
||||||
|
#else
|
||||||
|
material_name_phase = phases%Keys()
|
||||||
|
material_name_homogenization = homogenizations%Keys()
|
||||||
|
#endif
|
||||||
|
|
||||||
allocate(homogenization_Nconstituents(homogenizations%length))
|
allocate(homogenization_Nconstituents(homogenizations%length))
|
||||||
do h=1, homogenizations%length
|
do h=1, homogenizations%length
|
||||||
|
@ -203,9 +209,9 @@ subroutine sanityCheck(materials,homogenizations)
|
||||||
|
|
||||||
end subroutine sanityCheck
|
end subroutine sanityCheck
|
||||||
|
|
||||||
|
#if defined (__GFORTRAN__)
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief Get all keys from a dictionary
|
!> @brief %keys() is broken on gfortran
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
function getKeys(dict)
|
function getKeys(dict)
|
||||||
|
|
||||||
|
@ -228,5 +234,6 @@ function getKeys(dict)
|
||||||
end do
|
end do
|
||||||
|
|
||||||
end function getKeys
|
end function getKeys
|
||||||
|
#endif
|
||||||
|
|
||||||
end module material
|
end module material
|
||||||
|
|
28
src/math.f90
28
src/math.f90
|
@ -84,38 +84,34 @@ contains
|
||||||
subroutine math_init
|
subroutine math_init
|
||||||
|
|
||||||
real(pReal), dimension(4) :: randTest
|
real(pReal), dimension(4) :: randTest
|
||||||
integer :: &
|
integer :: randSize
|
||||||
randSize, &
|
integer, dimension(:), allocatable :: seed
|
||||||
randomSeed !< fixed seeding for pseudo-random number generator, Default 0: use random seed
|
|
||||||
integer, dimension(:), allocatable :: randInit
|
|
||||||
class(tNode), pointer :: &
|
class(tNode), pointer :: &
|
||||||
num_generic
|
num_generic
|
||||||
|
|
||||||
|
|
||||||
print'(/,1x,a)', '<<<+- math init -+>>>'; flush(IO_STDOUT)
|
print'(/,1x,a)', '<<<+- math init -+>>>'; flush(IO_STDOUT)
|
||||||
|
|
||||||
num_generic => config_numerics%get('generic',defaultVal=emptyDict)
|
num_generic => config_numerics%get('generic',defaultVal=emptyDict)
|
||||||
randomSeed = num_generic%get_asInt('random_seed', defaultVal = 0)
|
|
||||||
|
|
||||||
call random_seed(size=randSize)
|
call random_seed(size=randSize)
|
||||||
allocate(randInit(randSize))
|
allocate(seed(randSize))
|
||||||
if (randomSeed > 0) then
|
|
||||||
randInit = randomSeed
|
if (num_generic%contains('random_seed')) then
|
||||||
|
seed = num_generic%get_as1dInt('random_seed',requiredSize=randSize)
|
||||||
else
|
else
|
||||||
call random_seed()
|
call random_seed()
|
||||||
call random_seed(get = randInit)
|
call random_seed(get = seed)
|
||||||
randInit(2:randSize) = randInit(1)
|
|
||||||
end if
|
end if
|
||||||
|
|
||||||
call random_seed(put = randInit)
|
call random_seed(put = seed)
|
||||||
call random_number(randTest)
|
call random_number(randTest)
|
||||||
|
|
||||||
print'(/,a,i2)', ' size of random seed: ', randSize
|
print'(/,a,i2)', ' size of random seed: ', randSize
|
||||||
print'( a,i0)', ' value of random seed: ', randInit(1)
|
print*, 'value of random seed: ', seed
|
||||||
print'( a,4(/,26x,f17.14),/)', ' start of random sequence: ', randTest
|
print'( a,4(/,26x,f17.14))', ' start of random sequence: ', randTest
|
||||||
|
|
||||||
call random_seed(put = randInit)
|
call selfTest()
|
||||||
|
|
||||||
call selfTest
|
|
||||||
|
|
||||||
end subroutine math_init
|
end subroutine math_init
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ program DAMASK_mesh
|
||||||
type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases
|
type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases
|
||||||
type(tSolutionState), allocatable, dimension(:) :: solres
|
type(tSolutionState), allocatable, dimension(:) :: solres
|
||||||
PetscInt :: faceSet, currentFaceSet, dimPlex
|
PetscInt :: faceSet, currentFaceSet, dimPlex
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer(kind(COMPONENT_UNDEFINED_ID)) :: ID
|
integer(kind(COMPONENT_UNDEFINED_ID)) :: ID
|
||||||
external :: &
|
external :: &
|
||||||
quit
|
quit
|
||||||
|
@ -98,8 +98,8 @@ program DAMASK_mesh
|
||||||
if (maxCutBack < 0) call IO_error(301,ext_msg='maxCutBack')
|
if (maxCutBack < 0) call IO_error(301,ext_msg='maxCutBack')
|
||||||
|
|
||||||
! reading basic information from load case file and allocate data structure containing load cases
|
! reading basic information from load case file and allocate data structure containing load cases
|
||||||
call DMGetDimension(geomMesh,dimPlex,ierr) !< dimension of mesh (2D or 3D)
|
call DMGetDimension(geomMesh,dimPlex,err_PETSc) !< dimension of mesh (2D or 3D)
|
||||||
CHKERRA(ierr)
|
CHKERRA(err_PETSc)
|
||||||
allocate(solres(1))
|
allocate(solres(1))
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -50,7 +50,7 @@ module FEM_utilities
|
||||||
type, public :: tSolutionState !< return type of solution from FEM solver variants
|
type, public :: tSolutionState !< return type of solution from FEM solver variants
|
||||||
logical :: converged = .true.
|
logical :: converged = .true.
|
||||||
logical :: stagConverged = .true.
|
logical :: stagConverged = .true.
|
||||||
integer :: iterationsNeeded = 0
|
PetscInt :: iterationsNeeded = 0_pPETSCINT
|
||||||
end type tSolutionState
|
end type tSolutionState
|
||||||
|
|
||||||
type, public :: tComponentBC
|
type, public :: tComponentBC
|
||||||
|
@ -92,7 +92,7 @@ subroutine FEM_utilities_init
|
||||||
p_i !< integration order (quadrature rule)
|
p_i !< integration order (quadrature rule)
|
||||||
character(len=*), parameter :: &
|
character(len=*), parameter :: &
|
||||||
PETSCDEBUG = ' -snes_view -snes_monitor '
|
PETSCDEBUG = ' -snes_view -snes_monitor '
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
logical :: debugPETSc !< use some in debug defined options for more verbose PETSc solution
|
logical :: debugPETSc !< use some in debug defined options for more verbose PETSc solution
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,9 +103,9 @@ subroutine FEM_utilities_init
|
||||||
p_s = num_mesh%get_asInt('p_s',defaultVal = 2)
|
p_s = num_mesh%get_asInt('p_s',defaultVal = 2)
|
||||||
p_i = num_mesh%get_asInt('p_i',defaultVal = p_s)
|
p_i = num_mesh%get_asInt('p_i',defaultVal = p_s)
|
||||||
|
|
||||||
if (p_s < 1_pInt .or. p_s > size(FEM_nQuadrature,2)) &
|
if (p_s < 1 .or. p_s > size(FEM_nQuadrature,2)) &
|
||||||
call IO_error(821,ext_msg='shape function order (p_s) out of bounds')
|
call IO_error(821,ext_msg='shape function order (p_s) out of bounds')
|
||||||
if (p_i < max(1_pInt,p_s-1_pInt) .or. p_i > p_s) &
|
if (p_i < max(1,p_s-1) .or. p_i > p_s) &
|
||||||
call IO_error(821,ext_msg='integration order (p_i) out of bounds')
|
call IO_error(821,ext_msg='integration order (p_i) out of bounds')
|
||||||
|
|
||||||
debug_mesh => config_debug%get('mesh',defaultVal=emptyList)
|
debug_mesh => config_debug%get('mesh',defaultVal=emptyList)
|
||||||
|
@ -116,20 +116,20 @@ subroutine FEM_utilities_init
|
||||||
trim(PETScDebug), &
|
trim(PETScDebug), &
|
||||||
'add more using the "PETSc_options" keyword in numerics.yaml'
|
'add more using the "PETSc_options" keyword in numerics.yaml'
|
||||||
flush(IO_STDOUT)
|
flush(IO_STDOUT)
|
||||||
call PetscOptionsClear(PETSC_NULL_OPTIONS,ierr)
|
call PetscOptionsClear(PETSC_NULL_OPTIONS,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
if(debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(PETSCDEBUG),ierr)
|
if(debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(PETSCDEBUG),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type newtonls &
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type newtonls &
|
||||||
&-mechanical_snes_linesearch_type cp -mechanical_snes_ksp_ew &
|
&-mechanical_snes_linesearch_type cp -mechanical_snes_ksp_ew &
|
||||||
&-mechanical_snes_ksp_ew_rtol0 0.01 -mechanical_snes_ksp_ew_rtolmax 0.01 &
|
&-mechanical_snes_ksp_ew_rtol0 0.01 -mechanical_snes_ksp_ew_rtolmax 0.01 &
|
||||||
&-mechanical_ksp_type fgmres -mechanical_ksp_max_it 25', ierr)
|
&-mechanical_ksp_type fgmres -mechanical_ksp_max_it 25', err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_mesh%get_asString('PETSc_options',defaultVal=''),ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_mesh%get_asString('PETSc_options',defaultVal=''),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
write(petsc_optionsOrder,'(a,i0)') '-mechFE_petscspace_degree ', p_s
|
write(petsc_optionsOrder,'(a,i0)') '-mechFE_petscspace_degree ', p_s
|
||||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(petsc_optionsOrder),ierr)
|
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(petsc_optionsOrder),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
wgt = 1.0/real(mesh_maxNips*mesh_NcpElemsGlobal,pReal)
|
wgt = 1.0/real(mesh_maxNips*mesh_NcpElemsGlobal,pReal)
|
||||||
|
|
||||||
|
@ -144,10 +144,9 @@ subroutine utilities_constitutiveResponse(timeinc,P_av,forwardData)
|
||||||
|
|
||||||
real(pReal), intent(in) :: timeinc !< loading time
|
real(pReal), intent(in) :: timeinc !< loading time
|
||||||
logical, intent(in) :: forwardData !< age results
|
logical, intent(in) :: forwardData !< age results
|
||||||
|
|
||||||
real(pReal),intent(out), dimension(3,3) :: P_av !< average PK stress
|
real(pReal),intent(out), dimension(3,3) :: P_av !< average PK stress
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
print'(/,1x,a)', '... evaluating constitutive response ......................................'
|
print'(/,1x,a)', '... evaluating constitutive response ......................................'
|
||||||
|
|
||||||
|
@ -157,7 +156,9 @@ subroutine utilities_constitutiveResponse(timeinc,P_av,forwardData)
|
||||||
cutBack = .false.
|
cutBack = .false.
|
||||||
|
|
||||||
P_av = sum(homogenization_P,dim=3) * wgt
|
P_av = sum(homogenization_P,dim=3) * wgt
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,P_av,9,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,P_av,9_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
|
|
||||||
end subroutine utilities_constitutiveResponse
|
end subroutine utilities_constitutiveResponse
|
||||||
|
|
||||||
|
@ -174,26 +175,29 @@ subroutine utilities_projectBCValues(localVec,section,field,comp,bcPointsIS,BCVa
|
||||||
PetscInt, pointer :: bcPoints(:)
|
PetscInt, pointer :: bcPoints(:)
|
||||||
PetscScalar, pointer :: localArray(:)
|
PetscScalar, pointer :: localArray(:)
|
||||||
PetscScalar :: BCValue,BCDotValue,timeinc
|
PetscScalar :: BCValue,BCDotValue,timeinc
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
|
|
||||||
call PetscSectionGetFieldComponents(section,field,numComp,ierr); CHKERRQ(ierr)
|
call PetscSectionGetFieldComponents(section,field,numComp,err_PETSc)
|
||||||
call ISGetSize(bcPointsIS,nBcPoints,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
if (nBcPoints > 0) call ISGetIndicesF90(bcPointsIS,bcPoints,ierr)
|
call ISGetSize(bcPointsIS,nBcPoints,err_PETSc)
|
||||||
call VecGetArrayF90(localVec,localArray,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
if (nBcPoints > 0) call ISGetIndicesF90(bcPointsIS,bcPoints,err_PETSc)
|
||||||
|
call VecGetArrayF90(localVec,localArray,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
do point = 1, nBcPoints
|
do point = 1, nBcPoints
|
||||||
call PetscSectionGetFieldDof(section,bcPoints(point),field,numDof,ierr)
|
call PetscSectionGetFieldDof(section,bcPoints(point),field,numDof,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscSectionGetFieldOffset(section,bcPoints(point),field,offset,ierr)
|
call PetscSectionGetFieldOffset(section,bcPoints(point),field,offset,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
do dof = offset+comp+1, offset+numDof, numComp
|
do dof = offset+comp+1, offset+numDof, numComp
|
||||||
localArray(dof) = localArray(dof) + BCValue + BCDotValue*timeinc
|
localArray(dof) = localArray(dof) + BCValue + BCDotValue*timeinc
|
||||||
end do
|
end do
|
||||||
end do
|
end do
|
||||||
call VecRestoreArrayF90(localVec,localArray,ierr); CHKERRQ(ierr)
|
call VecRestoreArrayF90(localVec,localArray,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call VecAssemblyBegin(localVec, ierr); CHKERRQ(ierr)
|
call VecAssemblyBegin(localVec, err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call VecAssemblyEnd (localVec, ierr); CHKERRQ(ierr)
|
call VecAssemblyEnd (localVec, err_PETSc); CHKERRQ(err_PETSc)
|
||||||
if (nBcPoints > 0) call ISRestoreIndicesF90(bcPointsIS,bcPoints,ierr)
|
if (nBcPoints > 0) call ISRestoreIndicesF90(bcPointsIS,bcPoints,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine utilities_projectBCValues
|
end subroutine utilities_projectBCValues
|
||||||
|
|
||||||
|
|
|
@ -71,21 +71,22 @@ subroutine discretization_mesh_init(restart)
|
||||||
|
|
||||||
logical, intent(in) :: restart
|
logical, intent(in) :: restart
|
||||||
|
|
||||||
integer :: dimPlex, &
|
PetscInt :: dimPlex, &
|
||||||
mesh_Nnodes, & !< total number of nodes in mesh
|
mesh_Nnodes, & !< total number of nodes in mesh
|
||||||
j, &
|
j, &
|
||||||
debug_element, debug_ip
|
debug_element, debug_ip
|
||||||
PetscSF :: sf
|
PetscSF :: sf
|
||||||
DM :: globalMesh
|
DM :: globalMesh
|
||||||
PetscInt :: nFaceSets
|
PetscInt :: nFaceSets, Nboundaries, NelemsGlobal, Nelems
|
||||||
PetscInt, pointer, dimension(:) :: pFaceSets
|
PetscInt, pointer, dimension(:) :: pFaceSets
|
||||||
IS :: faceSetIS
|
IS :: faceSetIS
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
integer, dimension(:), allocatable :: &
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
PetscInt, dimension(:), allocatable :: &
|
||||||
materialAt
|
materialAt
|
||||||
class(tNode), pointer :: &
|
class(tNode), pointer :: &
|
||||||
num_mesh
|
num_mesh
|
||||||
integer :: p_i !< integration order (quadrature rule)
|
integer :: p_i, dim !< integration order (quadrature rule)
|
||||||
type(tvec) :: coords_node0
|
type(tvec) :: coords_node0
|
||||||
|
|
||||||
print'(/,1x,a)', '<<<+- discretization_mesh init -+>>>'
|
print'(/,1x,a)', '<<<+- discretization_mesh init -+>>>'
|
||||||
|
@ -100,56 +101,64 @@ subroutine discretization_mesh_init(restart)
|
||||||
debug_element = config_debug%get_asInt('element',defaultVal=1)
|
debug_element = config_debug%get_asInt('element',defaultVal=1)
|
||||||
debug_ip = config_debug%get_asInt('integrationpoint',defaultVal=1)
|
debug_ip = config_debug%get_asInt('integrationpoint',defaultVal=1)
|
||||||
|
|
||||||
call DMPlexCreateFromFile(PETSC_COMM_WORLD,interface_geomFile,PETSC_TRUE,globalMesh,ierr)
|
call DMPlexCreateFromFile(PETSC_COMM_WORLD,interface_geomFile,PETSC_TRUE,globalMesh,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetDimension(globalMesh,dimPlex,ierr)
|
call DMGetDimension(globalMesh,dimPlex,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetStratumSize(globalMesh,'depth',dimPlex,mesh_NcpElemsGlobal,ierr)
|
call DMGetStratumSize(globalMesh,'depth',dimPlex,NelemsGlobal,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
print'()'
|
mesh_NcpElemsGlobal = int(NelemsGlobal)
|
||||||
call DMView(globalMesh, PETSC_VIEWER_STDOUT_WORLD,ierr)
|
call DMView(globalMesh, PETSC_VIEWER_STDOUT_WORLD,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
! get number of IDs in face sets (for boundary conditions?)
|
! get number of IDs in face sets (for boundary conditions?)
|
||||||
call DMGetLabelSize(globalMesh,'Face Sets',mesh_Nboundaries,ierr)
|
call DMGetLabelSize(globalMesh,'Face Sets',Nboundaries,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call MPI_Bcast(mesh_Nboundaries,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
|
mesh_Nboundaries = int(Nboundaries)
|
||||||
call MPI_Bcast(mesh_NcpElemsGlobal,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(mesh_Nboundaries,1_MPI_INTEGER_KIND,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
call MPI_Bcast(dimPlex,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
call MPI_Bcast(mesh_NcpElemsGlobal,1_MPI_INTEGER_KIND,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
dim = int(dimPlex)
|
||||||
|
call MPI_Bcast(dim,1_MPI_INTEGER_KIND,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
|
dimPlex = int(dim,pPETSCINT)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
if (worldrank == 0) then
|
if (worldrank == 0) then
|
||||||
call DMClone(globalMesh,geomMesh,ierr)
|
call DMClone(globalMesh,geomMesh,err_PETSc)
|
||||||
else
|
else
|
||||||
call DMPlexDistribute(globalMesh,0,sf,geomMesh,ierr)
|
call DMPlexDistribute(globalMesh,0_pPETSCINT,sf,geomMesh,err_PETSc)
|
||||||
endif
|
endif
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
allocate(mesh_boundaries(mesh_Nboundaries), source = 0)
|
allocate(mesh_boundaries(mesh_Nboundaries), source = 0_pPETSCINT)
|
||||||
call DMGetLabelSize(globalMesh,'Face Sets',nFaceSets,ierr)
|
call DMGetLabelSize(globalMesh,'Face Sets',nFaceSets,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetLabelIdIS(globalMesh,'Face Sets',faceSetIS,ierr)
|
call DMGetLabelIdIS(globalMesh,'Face Sets',faceSetIS,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
if (nFaceSets > 0) then
|
if (nFaceSets > 0) then
|
||||||
call ISGetIndicesF90(faceSetIS,pFaceSets,ierr)
|
call ISGetIndicesF90(faceSetIS,pFaceSets,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
mesh_boundaries(1:nFaceSets) = pFaceSets
|
mesh_boundaries(1:nFaceSets) = pFaceSets
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call ISRestoreIndicesF90(faceSetIS,pFaceSets,ierr)
|
call ISRestoreIndicesF90(faceSetIS,pFaceSets,err_PETSc)
|
||||||
endif
|
endif
|
||||||
call MPI_Bcast(mesh_boundaries,mesh_Nboundaries,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
|
call MPI_Bcast(mesh_boundaries,mesh_Nboundaries,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
call DMDestroy(globalMesh,ierr); CHKERRQ(ierr)
|
call DMDestroy(globalMesh,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
call DMGetStratumSize(geomMesh,'depth',dimPlex,mesh_NcpElems,ierr)
|
call DMGetStratumSize(geomMesh,'depth',dimPlex,Nelems,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetStratumSize(geomMesh,'depth',0,mesh_Nnodes,ierr)
|
mesh_NcpElems = int(Nelems)
|
||||||
CHKERRQ(ierr)
|
call DMGetStratumSize(geomMesh,'depth',0_pPETSCINT,mesh_Nnodes,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
! Get initial nodal coordinates
|
! Get initial nodal coordinates
|
||||||
call DMGetCoordinates(geomMesh,coords_node0,ierr)
|
call DMGetCoordinates(geomMesh,coords_node0,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call VecGetArrayF90(coords_node0, mesh_node0_temp,ierr)
|
call VecGetArrayF90(coords_node0, mesh_node0_temp,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
mesh_maxNips = FEM_nQuadrature(dimPlex,p_i)
|
mesh_maxNips = FEM_nQuadrature(dimPlex,p_i)
|
||||||
|
|
||||||
|
@ -158,10 +167,10 @@ subroutine discretization_mesh_init(restart)
|
||||||
|
|
||||||
allocate(materialAt(mesh_NcpElems))
|
allocate(materialAt(mesh_NcpElems))
|
||||||
do j = 1, mesh_NcpElems
|
do j = 1, mesh_NcpElems
|
||||||
call DMGetLabelValue(geomMesh,'Cell Sets',j-1,materialAt(j),ierr)
|
call DMGetLabelValue(geomMesh,'Cell Sets',j-1,materialAt(j),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
enddo
|
enddo
|
||||||
materialAt = materialAt + 1
|
materialAt = materialAt + 1_pPETSCINT
|
||||||
|
|
||||||
if (debug_element < 1 .or. debug_element > mesh_NcpElems) call IO_error(602,ext_msg='element')
|
if (debug_element < 1 .or. debug_element > mesh_NcpElems) call IO_error(602,ext_msg='element')
|
||||||
if (debug_ip < 1 .or. debug_ip > mesh_maxNips) call IO_error(602,ext_msg='IP')
|
if (debug_ip < 1 .or. debug_ip > mesh_maxNips) call IO_error(602,ext_msg='IP')
|
||||||
|
@ -170,7 +179,7 @@ subroutine discretization_mesh_init(restart)
|
||||||
mesh_node0(1:dimPlex,:) = reshape(mesh_node0_temp,[dimPlex,mesh_Nnodes])
|
mesh_node0(1:dimPlex,:) = reshape(mesh_node0_temp,[dimPlex,mesh_Nnodes])
|
||||||
|
|
||||||
|
|
||||||
call discretization_init(materialAt,&
|
call discretization_init(int(materialAt),&
|
||||||
reshape(mesh_ipCoordinates,[3,mesh_maxNips*mesh_NcpElems]), &
|
reshape(mesh_ipCoordinates,[3,mesh_maxNips*mesh_NcpElems]), &
|
||||||
mesh_node0)
|
mesh_node0)
|
||||||
|
|
||||||
|
@ -188,16 +197,17 @@ subroutine mesh_FEM_build_ipVolumes(dimPlex)
|
||||||
PetscReal :: vol
|
PetscReal :: vol
|
||||||
PetscReal, pointer,dimension(:) :: pCent, pNorm
|
PetscReal, pointer,dimension(:) :: pCent, pNorm
|
||||||
PetscInt :: cellStart, cellEnd, cell
|
PetscInt :: cellStart, cellEnd, cell
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
allocate(mesh_ipVolume(mesh_maxNips,mesh_NcpElems),source=0.0_pReal)
|
allocate(mesh_ipVolume(mesh_maxNips,mesh_NcpElems),source=0.0_pReal)
|
||||||
|
|
||||||
call DMPlexGetHeightStratum(geomMesh,0,cellStart,cellEnd,ierr); CHKERRQ(ierr)
|
call DMPlexGetHeightStratum(geomMesh,0_pPETSCINT,cellStart,cellEnd,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
allocate(pCent(dimPlex))
|
allocate(pCent(dimPlex))
|
||||||
allocate(pNorm(dimPlex))
|
allocate(pNorm(dimPlex))
|
||||||
do cell = cellStart, cellEnd-1
|
do cell = cellStart, cellEnd-1
|
||||||
call DMPlexComputeCellGeometryFVM(geomMesh,cell,vol,pCent,pNorm,ierr)
|
call DMPlexComputeCellGeometryFVM(geomMesh,cell,vol,pCent,pNorm,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
mesh_ipVolume(:,cell+1) = vol/real(mesh_maxNips,pReal)
|
mesh_ipVolume(:,cell+1) = vol/real(mesh_maxNips,pReal)
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
|
@ -215,7 +225,7 @@ subroutine mesh_FEM_build_ipCoordinates(dimPlex,qPoints)
|
||||||
PetscReal, pointer,dimension(:) :: pV0, pCellJ, pInvcellJ
|
PetscReal, pointer,dimension(:) :: pV0, pCellJ, pInvcellJ
|
||||||
PetscReal :: detJ
|
PetscReal :: detJ
|
||||||
PetscInt :: cellStart, cellEnd, cell, qPt, dirI, dirJ, qOffset
|
PetscInt :: cellStart, cellEnd, cell, qPt, dirI, dirJ, qOffset
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
|
|
||||||
allocate(mesh_ipCoordinates(3,mesh_maxNips,mesh_NcpElems),source=0.0_pReal)
|
allocate(mesh_ipCoordinates(3,mesh_maxNips,mesh_NcpElems),source=0.0_pReal)
|
||||||
|
@ -223,10 +233,11 @@ subroutine mesh_FEM_build_ipCoordinates(dimPlex,qPoints)
|
||||||
allocate(pV0(dimPlex))
|
allocate(pV0(dimPlex))
|
||||||
allocatE(pCellJ(dimPlex**2))
|
allocatE(pCellJ(dimPlex**2))
|
||||||
allocatE(pinvCellJ(dimPlex**2))
|
allocatE(pinvCellJ(dimPlex**2))
|
||||||
call DMPlexGetHeightStratum(geomMesh,0,cellStart,cellEnd,ierr); CHKERRQ(ierr)
|
call DMPlexGetHeightStratum(geomMesh,0_pPETSCINT,cellStart,cellEnd,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
do cell = cellStart, cellEnd-1 !< loop over all elements
|
do cell = cellStart, cellEnd-1 !< loop over all elements
|
||||||
call DMPlexComputeCellGeometryAffineFEM(geomMesh,cell,pV0,pCellJ,pInvcellJ,detJ,ierr)
|
call DMPlexComputeCellGeometryAffineFEM(geomMesh,cell,pV0,pCellJ,pInvcellJ,detJ,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
qOffset = 0
|
qOffset = 0
|
||||||
do qPt = 1, mesh_maxNips
|
do qPt = 1, mesh_maxNips
|
||||||
do dirI = 1, dimPlex
|
do dirI = 1, dimPlex
|
||||||
|
|
|
@ -40,7 +40,7 @@ module mesh_mechanical_FEM
|
||||||
type(tSolutionParams) :: params
|
type(tSolutionParams) :: params
|
||||||
|
|
||||||
type, private :: tNumerics
|
type, private :: tNumerics
|
||||||
integer :: &
|
PetscInt :: &
|
||||||
p_i, & !< integration order (quadrature rule)
|
p_i, & !< integration order (quadrature rule)
|
||||||
itmax
|
itmax
|
||||||
logical :: &
|
logical :: &
|
||||||
|
@ -55,7 +55,8 @@ module mesh_mechanical_FEM
|
||||||
! PETSc data
|
! PETSc data
|
||||||
SNES :: mechanical_snes
|
SNES :: mechanical_snes
|
||||||
Vec :: solution, solution_rate, solution_local
|
Vec :: solution, solution_rate, solution_local
|
||||||
PetscInt :: dimPlex, cellDof, nQuadrature, nBasis
|
PetscInt :: dimPlex, cellDof, nBasis
|
||||||
|
integer :: nQuadrature
|
||||||
PetscReal, allocatable, target :: qPoints(:), qWeights(:)
|
PetscReal, allocatable, target :: qPoints(:), qWeights(:)
|
||||||
MatNullSpace :: matnull
|
MatNullSpace :: matnull
|
||||||
|
|
||||||
|
@ -104,11 +105,11 @@ subroutine FEM_mechanical_init(fieldBC)
|
||||||
PetscReal :: detJ
|
PetscReal :: detJ
|
||||||
PetscReal, allocatable, target :: cellJMat(:,:)
|
PetscReal, allocatable, target :: cellJMat(:,:)
|
||||||
|
|
||||||
PetscScalar, pointer :: px_scal(:)
|
PetscScalar, pointer, dimension(:) :: px_scal
|
||||||
PetscScalar, allocatable, target :: x_scal(:)
|
PetscScalar, allocatable, target, dimension(:) :: x_scal
|
||||||
|
|
||||||
character(len=*), parameter :: prefix = 'mechFE_'
|
character(len=*), parameter :: prefix = 'mechFE_'
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
real(pReal), dimension(3,3) :: devNull
|
real(pReal), dimension(3,3) :: devNull
|
||||||
class(tNode), pointer :: &
|
class(tNode), pointer :: &
|
||||||
num_mesh
|
num_mesh
|
||||||
|
@ -118,8 +119,8 @@ subroutine FEM_mechanical_init(fieldBC)
|
||||||
!-----------------------------------------------------------------------------
|
!-----------------------------------------------------------------------------
|
||||||
! read numerical parametes and do sanity checks
|
! read numerical parametes and do sanity checks
|
||||||
num_mesh => config_numerics%get('mesh',defaultVal=emptyDict)
|
num_mesh => config_numerics%get('mesh',defaultVal=emptyDict)
|
||||||
num%p_i = num_mesh%get_asInt('p_i',defaultVal = 2)
|
num%p_i = int(num_mesh%get_asInt('p_i',defaultVal = 2),pPETSCINT)
|
||||||
num%itmax = num_mesh%get_asInt('itmax',defaultVal=250)
|
num%itmax = int(num_mesh%get_asInt('itmax',defaultVal=250),pPETSCINT)
|
||||||
num%BBarStabilisation = num_mesh%get_asBool('bbarstabilisation',defaultVal = .false.)
|
num%BBarStabilisation = num_mesh%get_asBool('bbarstabilisation',defaultVal = .false.)
|
||||||
num%eps_struct_atol = num_mesh%get_asFloat('eps_struct_atol', defaultVal = 1.0e-10_pReal)
|
num%eps_struct_atol = num_mesh%get_asFloat('eps_struct_atol', defaultVal = 1.0e-10_pReal)
|
||||||
num%eps_struct_rtol = num_mesh%get_asFloat('eps_struct_rtol', defaultVal = 1.0e-4_pReal)
|
num%eps_struct_rtol = num_mesh%get_asFloat('eps_struct_rtol', defaultVal = 1.0e-4_pReal)
|
||||||
|
@ -130,8 +131,8 @@ subroutine FEM_mechanical_init(fieldBC)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! Setup FEM mech mesh
|
! Setup FEM mech mesh
|
||||||
call DMClone(geomMesh,mechanical_mesh,ierr); CHKERRQ(ierr)
|
call DMClone(geomMesh,mechanical_mesh,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGetDimension(mechanical_mesh,dimPlex,ierr); CHKERRQ(ierr)
|
call DMGetDimension(mechanical_mesh,dimPlex,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! Setup FEM mech discretization
|
! Setup FEM mech discretization
|
||||||
|
@ -140,96 +141,104 @@ subroutine FEM_mechanical_init(fieldBC)
|
||||||
nQuadrature = FEM_nQuadrature( dimPlex,num%p_i)
|
nQuadrature = FEM_nQuadrature( dimPlex,num%p_i)
|
||||||
qPointsP => qPoints
|
qPointsP => qPoints
|
||||||
qWeightsP => qWeights
|
qWeightsP => qWeights
|
||||||
call PetscQuadratureCreate(PETSC_COMM_SELF,mechQuad,ierr); CHKERRQ(ierr)
|
call PetscQuadratureCreate(PETSC_COMM_SELF,mechQuad,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
nc = dimPlex
|
nc = dimPlex
|
||||||
call PetscQuadratureSetData(mechQuad,dimPlex,nc,nQuadrature,qPointsP,qWeightsP,ierr)
|
call PetscQuadratureSetData(mechQuad,dimPlex,nc,int(nQuadrature,pPETSCINT),qPointsP,qWeightsP,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscFECreateDefault(PETSC_COMM_SELF,dimPlex,nc,PETSC_TRUE,prefix, &
|
call PetscFECreateDefault(PETSC_COMM_SELF,dimPlex,nc,PETSC_TRUE,prefix, &
|
||||||
num%p_i,mechFE,ierr); CHKERRQ(ierr)
|
num%p_i,mechFE,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call PetscFESetQuadrature(mechFE,mechQuad,ierr); CHKERRQ(ierr)
|
call PetscFESetQuadrature(mechFE,mechQuad,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call PetscFEGetDimension(mechFE,nBasis,ierr); CHKERRQ(ierr)
|
call PetscFEGetDimension(mechFE,nBasis,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
nBasis = nBasis/nc
|
nBasis = nBasis/nc
|
||||||
call DMAddField(mechanical_mesh,PETSC_NULL_DMLABEL,mechFE,ierr); CHKERRQ(ierr)
|
call DMAddField(mechanical_mesh,PETSC_NULL_DMLABEL,mechFE,err_PETSc)
|
||||||
call DMCreateDS(mechanical_mesh,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetDS(mechanical_mesh,mechDS,ierr); CHKERRQ(ierr)
|
call DMCreateDS(mechanical_mesh,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call PetscDSGetTotalDimension(mechDS,cellDof,ierr); CHKERRQ(ierr)
|
call DMGetDS(mechanical_mesh,mechDS,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call PetscFEDestroy(mechFE,ierr); CHKERRQ(ierr)
|
call PetscDSGetTotalDimension(mechDS,cellDof,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call PetscQuadratureDestroy(mechQuad,ierr); CHKERRQ(ierr)
|
call PetscFEDestroy(mechFE,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
call PetscQuadratureDestroy(mechQuad,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! Setup FEM mech boundary conditions
|
! Setup FEM mech boundary conditions
|
||||||
call DMGetLabel(mechanical_mesh,'Face Sets',BCLabel,ierr); CHKERRQ(ierr)
|
call DMGetLabel(mechanical_mesh,'Face Sets',BCLabel,err_PETSc)
|
||||||
call DMPlexLabelComplete(mechanical_mesh,BCLabel,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetLocalSection(mechanical_mesh,section,ierr); CHKERRQ(ierr)
|
call DMPlexLabelComplete(mechanical_mesh,BCLabel,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
call DMGetLocalSection(mechanical_mesh,section,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
allocate(pnumComp(1), source=dimPlex)
|
allocate(pnumComp(1), source=dimPlex)
|
||||||
allocate(pnumDof(0:dimPlex), source = 0)
|
allocate(pnumDof(0:dimPlex), source = 0_pPETSCINT)
|
||||||
do topologDim = 0, dimPlex
|
do topologDim = 0, dimPlex
|
||||||
call DMPlexGetDepthStratum(mechanical_mesh,topologDim,cellStart,cellEnd,ierr)
|
call DMPlexGetDepthStratum(mechanical_mesh,topologDim,cellStart,cellEnd,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscSectionGetDof(section,cellStart,pnumDof(topologDim),ierr)
|
call PetscSectionGetDof(section,cellStart,pnumDof(topologDim),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
enddo
|
enddo
|
||||||
numBC = 0
|
numBC = 0
|
||||||
do field = 1, dimPlex; do faceSet = 1, mesh_Nboundaries
|
do field = 1, dimPlex; do faceSet = 1, mesh_Nboundaries
|
||||||
if (fieldBC%componentBC(field)%Mask(faceSet)) numBC = numBC + 1
|
if (fieldBC%componentBC(field)%Mask(faceSet)) numBC = numBC + 1
|
||||||
enddo; enddo
|
enddo; enddo
|
||||||
allocate(pbcField(numBC), source=0)
|
allocate(pbcField(numBC), source=0_pPETSCINT)
|
||||||
allocate(pbcComps(numBC))
|
allocate(pbcComps(numBC))
|
||||||
allocate(pbcPoints(numBC))
|
allocate(pbcPoints(numBC))
|
||||||
numBC = 0
|
numBC = 0
|
||||||
do field = 1, dimPlex; do faceSet = 1, mesh_Nboundaries
|
do field = 1, dimPlex; do faceSet = 1, mesh_Nboundaries
|
||||||
if (fieldBC%componentBC(field)%Mask(faceSet)) then
|
if (fieldBC%componentBC(field)%Mask(faceSet)) then
|
||||||
numBC = numBC + 1
|
numBC = numBC + 1
|
||||||
call ISCreateGeneral(PETSC_COMM_WORLD,1,[field-1],PETSC_COPY_VALUES,pbcComps(numBC),ierr)
|
call ISCreateGeneral(PETSC_COMM_WORLD,1_pPETSCINT,[field-1],PETSC_COPY_VALUES,pbcComps(numBC),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetStratumSize(mechanical_mesh,'Face Sets',mesh_boundaries(faceSet),bcSize,ierr)
|
call DMGetStratumSize(mechanical_mesh,'Face Sets',mesh_boundaries(faceSet),bcSize,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
if (bcSize > 0) then
|
if (bcSize > 0) then
|
||||||
call DMGetStratumIS(mechanical_mesh,'Face Sets',mesh_boundaries(faceSet),bcPoint,ierr)
|
call DMGetStratumIS(mechanical_mesh,'Face Sets',mesh_boundaries(faceSet),bcPoint,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call ISGetIndicesF90(bcPoint,pBcPoint,ierr); CHKERRQ(ierr)
|
call ISGetIndicesF90(bcPoint,pBcPoint,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call ISCreateGeneral(PETSC_COMM_WORLD,bcSize,pBcPoint,PETSC_COPY_VALUES,pbcPoints(numBC),ierr)
|
call ISCreateGeneral(PETSC_COMM_WORLD,bcSize,pBcPoint,PETSC_COPY_VALUES,pbcPoints(numBC),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call ISRestoreIndicesF90(bcPoint,pBcPoint,ierr); CHKERRQ(ierr)
|
call ISRestoreIndicesF90(bcPoint,pBcPoint,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call ISDestroy(bcPoint,ierr); CHKERRQ(ierr)
|
call ISDestroy(bcPoint,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
else
|
else
|
||||||
call ISCreateGeneral(PETSC_COMM_WORLD,0,[0],PETSC_COPY_VALUES,pbcPoints(numBC),ierr)
|
call ISCreateGeneral(PETSC_COMM_WORLD,0_pPETSCINT,[0_pPETSCINT],PETSC_COPY_VALUES,pbcPoints(numBC),err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
enddo; enddo
|
enddo; enddo
|
||||||
call DMPlexCreateSection(mechanical_mesh,nolabel,pNumComp,pNumDof, &
|
call DMPlexCreateSection(mechanical_mesh,nolabel,pNumComp,pNumDof, &
|
||||||
numBC,pBcField,pBcComps,pBcPoints,PETSC_NULL_IS,section,ierr)
|
numBC,pBcField,pBcComps,pBcPoints,PETSC_NULL_IS,section,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMSetSection(mechanical_mesh,section,ierr); CHKERRQ(ierr)
|
call DMSetSection(mechanical_mesh,section,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
do faceSet = 1, numBC
|
do faceSet = 1, numBC
|
||||||
call ISDestroy(pbcPoints(faceSet),ierr); CHKERRQ(ierr)
|
call ISDestroy(pbcPoints(faceSet),err_PETSc); CHKERRQ(err_PETSc)
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! initialize solver specific parts of PETSc
|
! initialize solver specific parts of PETSc
|
||||||
call SNESCreate(PETSC_COMM_WORLD,mechanical_snes,ierr);CHKERRQ(ierr)
|
call SNESCreate(PETSC_COMM_WORLD,mechanical_snes,err_PETSc);CHKERRQ(err_PETSc)
|
||||||
call SNESSetOptionsPrefix(mechanical_snes,'mechanical_',ierr);CHKERRQ(ierr)
|
call SNESSetOptionsPrefix(mechanical_snes,'mechanical_',err_PETSc)
|
||||||
call SNESSetDM(mechanical_snes,mechanical_mesh,ierr); CHKERRQ(ierr) !< set the mesh for non-linear solver
|
CHKERRQ(err_PETSc)
|
||||||
call DMCreateGlobalVector(mechanical_mesh,solution ,ierr); CHKERRQ(ierr) !< locally owned displacement Dofs
|
call SNESSetDM(mechanical_snes,mechanical_mesh,err_PETSc) ! set the mesh for non-linear solver
|
||||||
call DMCreateGlobalVector(mechanical_mesh,solution_rate ,ierr); CHKERRQ(ierr) !< locally owned velocity Dofs to guess solution at next load step
|
CHKERRQ(err_PETSc)
|
||||||
call DMCreateLocalVector (mechanical_mesh,solution_local ,ierr); CHKERRQ(ierr) !< locally owned velocity Dofs to guess solution at next load step
|
call DMCreateGlobalVector(mechanical_mesh,solution, err_PETSc) ! locally owned displacement Dofs
|
||||||
call DMSNESSetFunctionLocal(mechanical_mesh,FEM_mechanical_formResidual,PETSC_NULL_VEC,ierr) !< function to evaluate residual forces
|
CHKERRQ(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
call DMCreateGlobalVector(mechanical_mesh,solution_rate, err_PETSc) ! locally owned velocity Dofs to guess solution at next load step
|
||||||
call DMSNESSetJacobianLocal(mechanical_mesh,FEM_mechanical_formJacobian,PETSC_NULL_VEC,ierr) !< function to evaluate stiffness matrix
|
CHKERRQ(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
call DMCreateLocalVector (mechanical_mesh,solution_local,err_PETSc) ! locally owned velocity Dofs to guess solution at next load step
|
||||||
call SNESSetMaxLinearSolveFailures(mechanical_snes, huge(1), ierr); CHKERRQ(ierr) !< ignore linear solve failures
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetConvergenceTest(mechanical_snes,FEM_mechanical_converged,PETSC_NULL_VEC,PETSC_NULL_FUNCTION,ierr)
|
call DMSNESSetFunctionLocal(mechanical_mesh,FEM_mechanical_formResidual,PETSC_NULL_VEC,err_PETSc) ! function to evaluate residual forces
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetTolerances(mechanical_snes,1.0,0.0,0.0,num%itmax,num%itmax,ierr)
|
call DMSNESSetJacobianLocal(mechanical_mesh,FEM_mechanical_formJacobian,PETSC_NULL_VEC,err_PETSc) ! function to evaluate stiffness matrix
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call SNESSetFromOptions(mechanical_snes,ierr); CHKERRQ(ierr)
|
call SNESSetMaxLinearSolveFailures(mechanical_snes, huge(1_pPETSCINT), err_PETSc) ! ignore linear solve failures
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetConvergenceTest(mechanical_snes,FEM_mechanical_converged,PETSC_NULL_VEC,PETSC_NULL_FUNCTION,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetTolerances(mechanical_snes,1.0,0.0,0.0,num%itmax,num%itmax,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESSetFromOptions(mechanical_snes,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! init fields
|
! init fields
|
||||||
call VecSet(solution ,0.0,ierr); CHKERRQ(ierr)
|
call VecSet(solution ,0.0,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call VecSet(solution_rate ,0.0,ierr); CHKERRQ(ierr)
|
call VecSet(solution_rate ,0.0,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
allocate(x_scal(cellDof))
|
allocate(x_scal(cellDof))
|
||||||
allocate(nodalWeightsP(1))
|
allocate(nodalWeightsP(1))
|
||||||
allocate(nodalPointsP(dimPlex))
|
allocate(nodalPointsP(dimPlex))
|
||||||
|
@ -237,26 +246,26 @@ subroutine FEM_mechanical_init(fieldBC)
|
||||||
allocate(pcellJ(dimPlex**2))
|
allocate(pcellJ(dimPlex**2))
|
||||||
allocate(pinvcellJ(dimPlex**2))
|
allocate(pinvcellJ(dimPlex**2))
|
||||||
allocate(cellJMat(dimPlex,dimPlex))
|
allocate(cellJMat(dimPlex,dimPlex))
|
||||||
call PetscDSGetDiscretization(mechDS,0,mechFE,ierr)
|
call PetscDSGetDiscretization(mechDS,0_pPETSCINT,mechFE,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscFEGetDualSpace(mechFE,mechDualSpace,ierr); CHKERRQ(ierr)
|
call PetscFEGetDualSpace(mechFE,mechDualSpace,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMPlexGetHeightStratum(mechanical_mesh,0,cellStart,cellEnd,ierr)
|
call DMPlexGetHeightStratum(mechanical_mesh,0_pPETSCINT,cellStart,cellEnd,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
do cell = cellStart, cellEnd-1 !< loop over all elements
|
do cell = cellStart, cellEnd-1 !< loop over all elements
|
||||||
x_scal = 0.0_pReal
|
x_scal = 0.0_pReal
|
||||||
call DMPlexComputeCellGeometryAffineFEM(mechanical_mesh,cell,pV0,pCellJ,pInvcellJ,detJ,ierr)
|
call DMPlexComputeCellGeometryAffineFEM(mechanical_mesh,cell,pV0,pCellJ,pInvcellJ,detJ,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
cellJMat = reshape(pCellJ,shape=[dimPlex,dimPlex])
|
cellJMat = reshape(pCellJ,shape=[dimPlex,dimPlex])
|
||||||
do basis = 0, nBasis*dimPlex-1, dimPlex
|
do basis = 0, nBasis*dimPlex-1, dimPlex
|
||||||
call PetscDualSpaceGetFunctional(mechDualSpace,basis,functional,ierr)
|
call PetscDualSpaceGetFunctional(mechDualSpace,basis,functional,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscQuadratureGetData(functional,dimPlex,nc,nNodalPoints,nodalPointsP,nodalWeightsP,ierr)
|
call PetscQuadratureGetData(functional,dimPlex,nc,nNodalPoints,nodalPointsP,nodalWeightsP,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
x_scal(basis+1:basis+dimPlex) = pV0 + matmul(transpose(cellJMat),nodalPointsP + 1.0_pReal)
|
x_scal(basis+1:basis+dimPlex) = pV0 + matmul(transpose(cellJMat),nodalPointsP + 1.0_pReal)
|
||||||
enddo
|
enddo
|
||||||
px_scal => x_scal
|
px_scal => x_scal
|
||||||
call DMPlexVecSetClosure(mechanical_mesh,section,solution_local,cell,px_scal,5,ierr)
|
call DMPlexVecSetClosure(mechanical_mesh,section,solution_local,cell,px_scal,5,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
enddo
|
enddo
|
||||||
call utilities_constitutiveResponse(0.0_pReal,devNull,.true.)
|
call utilities_constitutiveResponse(0.0_pReal,devNull,.true.)
|
||||||
|
|
||||||
|
@ -279,7 +288,7 @@ type(tSolutionState) function FEM_mechanical_solution( &
|
||||||
character(len=*), intent(in) :: &
|
character(len=*), intent(in) :: &
|
||||||
incInfoIn
|
incInfoIn
|
||||||
|
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
|
|
||||||
incInfo = incInfoIn
|
incInfo = incInfoIn
|
||||||
|
@ -289,8 +298,10 @@ type(tSolutionState) function FEM_mechanical_solution( &
|
||||||
params%timeinc = timeinc
|
params%timeinc = timeinc
|
||||||
params%fieldBC = fieldBC
|
params%fieldBC = fieldBC
|
||||||
|
|
||||||
call SNESSolve(mechanical_snes,PETSC_NULL_VEC,solution,ierr); CHKERRQ(ierr) ! solve mechanical_snes based on solution guess (result in solution)
|
call SNESSolve(mechanical_snes,PETSC_NULL_VEC,solution,err_PETSc) ! solve mechanical_snes based on solution guess (result in solution)
|
||||||
call SNESGetConvergedReason(mechanical_snes,reason,ierr); CHKERRQ(ierr) ! solution converged?
|
CHKERRQ(err_PETSc)
|
||||||
|
call SNESGetConvergedReason(mechanical_snes,reason,err_PETSc) ! solution converged?
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
terminallyIll = .false.
|
terminallyIll = .false.
|
||||||
|
|
||||||
if (reason < 1) then ! 0: still iterating (will not occur), negative -> convergence error
|
if (reason < 1) then ! 0: still iterating (will not occur), negative -> convergence error
|
||||||
|
@ -298,8 +309,8 @@ type(tSolutionState) function FEM_mechanical_solution( &
|
||||||
FEM_mechanical_solution%iterationsNeeded = num%itmax
|
FEM_mechanical_solution%iterationsNeeded = num%itmax
|
||||||
else ! >= 1 proper convergence (or terminally ill)
|
else ! >= 1 proper convergence (or terminally ill)
|
||||||
FEM_mechanical_solution%converged = .true.
|
FEM_mechanical_solution%converged = .true.
|
||||||
call SNESGetIterationNumber(mechanical_snes,FEM_mechanical_solution%iterationsNeeded,ierr)
|
call SNESGetIterationNumber(mechanical_snes,FEM_mechanical_solution%iterationsNeeded,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
print'(/,1x,a)', '==========================================================================='
|
print'(/,1x,a)', '==========================================================================='
|
||||||
|
@ -311,11 +322,12 @@ end function FEM_mechanical_solution
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief forms the FEM residual vector
|
!> @brief forms the FEM residual vector
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine FEM_mechanical_formResidual(dm_local,xx_local,f_local,dummy,ierr)
|
subroutine FEM_mechanical_formResidual(dm_local,xx_local,f_local,dummy,err_PETSc)
|
||||||
|
|
||||||
DM :: dm_local
|
DM :: dm_local
|
||||||
PetscObject,intent(in) :: dummy
|
PetscObject,intent(in) :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
PetscDS :: prob
|
PetscDS :: prob
|
||||||
Vec :: x_local, f_local, xx_local
|
Vec :: x_local, f_local, xx_local
|
||||||
|
@ -339,22 +351,25 @@ subroutine FEM_mechanical_formResidual(dm_local,xx_local,f_local,dummy,ierr)
|
||||||
allocate(pinvcellJ(dimPlex**2))
|
allocate(pinvcellJ(dimPlex**2))
|
||||||
allocate(x_scal(cellDof))
|
allocate(x_scal(cellDof))
|
||||||
|
|
||||||
call DMGetLocalSection(dm_local,section,ierr); CHKERRQ(ierr)
|
call DMGetLocalSection(dm_local,section,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGetDS(dm_local,prob,ierr); CHKERRQ(ierr)
|
call DMGetDS(dm_local,prob,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call PetscDSGetTabulation(prob,0,basisField,basisFieldDer,ierr)
|
call PetscDSGetTabulation(prob,0_pPETSCINT,basisField,basisFieldDer,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMPlexGetHeightStratum(dm_local,0,cellStart,cellEnd,ierr); CHKERRQ(ierr)
|
call DMPlexGetHeightStratum(dm_local,0_pPETSCINT,cellStart,cellEnd,err_PETSc)
|
||||||
call DMGetLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call VecWAXPY(x_local,1.0,xx_local,solution_local,ierr); CHKERRQ(ierr)
|
call DMGetLocalVector(dm_local,x_local,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call VecWAXPY(x_local,1.0,xx_local,solution_local,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
do field = 1, dimPlex; do face = 1, mesh_Nboundaries
|
do field = 1, dimPlex; do face = 1, mesh_Nboundaries
|
||||||
if (params%fieldBC%componentBC(field)%Mask(face)) then
|
if (params%fieldBC%componentBC(field)%Mask(face)) then
|
||||||
call DMGetStratumSize(dm_local,'Face Sets',mesh_boundaries(face),bcSize,ierr)
|
call DMGetStratumSize(dm_local,'Face Sets',mesh_boundaries(face),bcSize,err_PETSc)
|
||||||
if (bcSize > 0) then
|
if (bcSize > 0) then
|
||||||
call DMGetStratumIS(dm_local,'Face Sets',mesh_boundaries(face),bcPoints,ierr)
|
call DMGetStratumIS(dm_local,'Face Sets',mesh_boundaries(face),bcPoints,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call utilities_projectBCValues(x_local,section,0,field-1,bcPoints, &
|
call utilities_projectBCValues(x_local,section,0_pPETSCINT,field-1,bcPoints, &
|
||||||
0.0_pReal,params%fieldBC%componentBC(field)%Value(face),params%timeinc)
|
0.0_pReal,params%fieldBC%componentBC(field)%Value(face),params%timeinc)
|
||||||
call ISDestroy(bcPoints,ierr); CHKERRQ(ierr)
|
call ISDestroy(bcPoints,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
enddo; enddo
|
enddo; enddo
|
||||||
|
@ -363,12 +378,12 @@ subroutine FEM_mechanical_formResidual(dm_local,xx_local,f_local,dummy,ierr)
|
||||||
! evaluate field derivatives
|
! evaluate field derivatives
|
||||||
do cell = cellStart, cellEnd-1 !< loop over all elements
|
do cell = cellStart, cellEnd-1 !< loop over all elements
|
||||||
|
|
||||||
call PetscSectionGetNumFields(section,numFields,ierr)
|
call PetscSectionGetNumFields(section,numFields,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMPlexVecGetClosure(dm_local,section,x_local,cell,x_scal,ierr) !< get Dofs belonging to element
|
call DMPlexVecGetClosure(dm_local,section,x_local,cell,x_scal,err_PETSc) !< get Dofs belonging to element
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMPlexComputeCellGeometryAffineFEM(dm_local,cell,pV0,pCellJ,pInvcellJ,detJ,ierr)
|
call DMPlexComputeCellGeometryAffineFEM(dm_local,cell,pV0,pCellJ,pInvcellJ,detJ,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
IcellJMat = reshape(pInvcellJ,shape=[dimPlex,dimPlex])
|
IcellJMat = reshape(pInvcellJ,shape=[dimPlex,dimPlex])
|
||||||
do qPt = 0, nQuadrature-1
|
do qPt = 0, nQuadrature-1
|
||||||
m = cell*nQuadrature + qPt+1
|
m = cell*nQuadrature + qPt+1
|
||||||
|
@ -392,23 +407,24 @@ subroutine FEM_mechanical_formResidual(dm_local,xx_local,f_local,dummy,ierr)
|
||||||
|
|
||||||
enddo
|
enddo
|
||||||
endif
|
endif
|
||||||
call DMPlexVecRestoreClosure(dm_local,section,x_local,cell,x_scal,ierr)
|
call DMPlexVecRestoreClosure(dm_local,section,x_local,cell,x_scal,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! evaluate constitutive response
|
! evaluate constitutive response
|
||||||
call utilities_constitutiveResponse(params%timeinc,P_av,ForwardData)
|
call utilities_constitutiveResponse(params%timeinc,P_av,ForwardData)
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr)
|
call MPI_Allreduce(MPI_IN_PLACE,terminallyIll,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
ForwardData = .false.
|
ForwardData = .false.
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! integrating residual
|
! integrating residual
|
||||||
do cell = cellStart, cellEnd-1 !< loop over all elements
|
do cell = cellStart, cellEnd-1 !< loop over all elements
|
||||||
call DMPlexVecGetClosure(dm_local,section,x_local,cell,x_scal,ierr) !< get Dofs belonging to element
|
call DMPlexVecGetClosure(dm_local,section,x_local,cell,x_scal,err_PETSc) !< get Dofs belonging to element
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMPlexComputeCellGeometryAffineFEM(dm_local,cell,pV0,pCellJ,pInvcellJ,detJ,ierr)
|
call DMPlexComputeCellGeometryAffineFEM(dm_local,cell,pV0,pCellJ,pInvcellJ,detJ,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
IcellJMat = reshape(pInvcellJ,shape=[dimPlex,dimPlex])
|
IcellJMat = reshape(pInvcellJ,shape=[dimPlex,dimPlex])
|
||||||
f_scal = 0.0
|
f_scal = 0.0
|
||||||
do qPt = 0, nQuadrature-1
|
do qPt = 0, nQuadrature-1
|
||||||
|
@ -429,12 +445,12 @@ subroutine FEM_mechanical_formResidual(dm_local,xx_local,f_local,dummy,ierr)
|
||||||
enddo
|
enddo
|
||||||
f_scal = f_scal*abs(detJ)
|
f_scal = f_scal*abs(detJ)
|
||||||
pf_scal => f_scal
|
pf_scal => f_scal
|
||||||
call DMPlexVecSetClosure(dm_local,section,f_local,cell,pf_scal,ADD_VALUES,ierr)
|
call DMPlexVecSetClosure(dm_local,section,f_local,cell,pf_scal,ADD_VALUES,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMPlexVecRestoreClosure(dm_local,section,x_local,cell,x_scal,ierr)
|
call DMPlexVecRestoreClosure(dm_local,section,x_local,cell,x_scal,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
enddo
|
enddo
|
||||||
call DMRestoreLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
call DMRestoreLocalVector(dm_local,x_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine FEM_mechanical_formResidual
|
end subroutine FEM_mechanical_formResidual
|
||||||
|
|
||||||
|
@ -442,13 +458,13 @@ end subroutine FEM_mechanical_formResidual
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief forms the FEM stiffness matrix
|
!> @brief forms the FEM stiffness matrix
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine FEM_mechanical_formJacobian(dm_local,xx_local,Jac_pre,Jac,dummy,ierr)
|
subroutine FEM_mechanical_formJacobian(dm_local,xx_local,Jac_pre,Jac,dummy,err_PETSc)
|
||||||
|
|
||||||
|
|
||||||
DM :: dm_local
|
DM :: dm_local
|
||||||
Mat :: Jac_pre, Jac
|
Mat :: Jac_pre, Jac
|
||||||
PetscObject, intent(in) :: dummy
|
PetscObject, intent(in) :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
PetscDS :: prob
|
PetscDS :: prob
|
||||||
Vec :: x_local, xx_local
|
Vec :: x_local, xx_local
|
||||||
|
@ -478,34 +494,43 @@ subroutine FEM_mechanical_formJacobian(dm_local,xx_local,Jac_pre,Jac,dummy,ierr)
|
||||||
allocate(pcellJ(dimPlex**2))
|
allocate(pcellJ(dimPlex**2))
|
||||||
allocate(pinvcellJ(dimPlex**2))
|
allocate(pinvcellJ(dimPlex**2))
|
||||||
|
|
||||||
call MatSetOption(Jac,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE,ierr); CHKERRQ(ierr)
|
call MatSetOption(Jac,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE,err_PETSc)
|
||||||
call MatSetOption(Jac,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call MatZeroEntries(Jac,ierr); CHKERRQ(ierr)
|
call MatSetOption(Jac,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE,err_PETSc)
|
||||||
call DMGetDS(dm_local,prob,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call PetscDSGetTabulation(prob,0,basisField,basisFieldDer,ierr)
|
call MatZeroEntries(Jac,err_PETSc)
|
||||||
call DMGetLocalSection(dm_local,section,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGetGlobalSection(dm_local,gSection,ierr); CHKERRQ(ierr)
|
call DMGetDS(dm_local,prob,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call PetscDSGetTabulation(prob,0_pPETSCINT,basisField,basisFieldDer,err_PETSc)
|
||||||
|
call DMGetLocalSection(dm_local,section,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
call DMGetGlobalSection(dm_local,gSection,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
call DMGetLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
call DMGetLocalVector(dm_local,x_local,err_PETSc)
|
||||||
call VecWAXPY(x_local,1.0_pReal,xx_local,solution_local,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call VecWAXPY(x_local,1.0_pReal,xx_local,solution_local,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
do field = 1, dimPlex; do face = 1, mesh_Nboundaries
|
do field = 1, dimPlex; do face = 1, mesh_Nboundaries
|
||||||
if (params%fieldBC%componentBC(field)%Mask(face)) then
|
if (params%fieldBC%componentBC(field)%Mask(face)) then
|
||||||
call DMGetStratumSize(dm_local,'Face Sets',mesh_boundaries(face),bcSize,ierr)
|
call DMGetStratumSize(dm_local,'Face Sets',mesh_boundaries(face),bcSize,err_PETSc)
|
||||||
if (bcSize > 0) then
|
if (bcSize > 0) then
|
||||||
call DMGetStratumIS(dm_local,'Face Sets',mesh_boundaries(face),bcPoints,ierr)
|
call DMGetStratumIS(dm_local,'Face Sets',mesh_boundaries(face),bcPoints,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call utilities_projectBCValues(x_local,section,0,field-1,bcPoints, &
|
call utilities_projectBCValues(x_local,section,0_pPETSCINT,field-1,bcPoints, &
|
||||||
0.0_pReal,params%fieldBC%componentBC(field)%Value(face),params%timeinc)
|
0.0_pReal,params%fieldBC%componentBC(field)%Value(face),params%timeinc)
|
||||||
call ISDestroy(bcPoints,ierr); CHKERRQ(ierr)
|
call ISDestroy(bcPoints,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
enddo; enddo
|
enddo; enddo
|
||||||
call DMPlexGetHeightStratum(dm_local,0,cellStart,cellEnd,ierr); CHKERRQ(ierr)
|
call DMPlexGetHeightStratum(dm_local,0_pPETSCINT,cellStart,cellEnd,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
do cell = cellStart, cellEnd-1 !< loop over all elements
|
do cell = cellStart, cellEnd-1 !< loop over all elements
|
||||||
call DMPlexVecGetClosure(dm_local,section,x_local,cell,x_scal,ierr) !< get Dofs belonging to element
|
call DMPlexVecGetClosure(dm_local,section,x_local,cell,x_scal,err_PETSc) !< get Dofs belonging to element
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMPlexComputeCellGeometryAffineFEM(dm_local,cell,pV0,pCellJ,pInvcellJ,detJ,ierr)
|
call DMPlexComputeCellGeometryAffineFEM(dm_local,cell,pV0,pCellJ,pInvcellJ,detJ,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
K_eA = 0.0
|
K_eA = 0.0
|
||||||
K_eB = 0.0
|
K_eB = 0.0
|
||||||
MatB = 0.0
|
MatB = 0.0
|
||||||
|
@ -531,11 +556,11 @@ subroutine FEM_mechanical_formJacobian(dm_local,xx_local,Jac_pre,Jac,dummy,ierr)
|
||||||
FInv = math_inv33(F)
|
FInv = math_inv33(F)
|
||||||
K_eA = K_eA + matmul(transpose(BMat),MatA)*math_det33(FInv)**(1.0/real(dimPlex))
|
K_eA = K_eA + matmul(transpose(BMat),MatA)*math_det33(FInv)**(1.0/real(dimPlex))
|
||||||
K_eB = K_eB - &
|
K_eB = K_eB - &
|
||||||
matmul(transpose(matmul(reshape(homogenization_F(1:dimPlex,1:dimPlex,m),shape=[dimPlex*dimPlex,1]), &
|
matmul(transpose(matmul(reshape(homogenization_F(1:dimPlex,1:dimPlex,m),shape=[dimPlex**2,1_pPETSCINT]), &
|
||||||
matmul(reshape(FInv(1:dimPlex,1:dimPlex), &
|
matmul(reshape(FInv(1:dimPlex,1:dimPlex), &
|
||||||
shape=[1,dimPlex*dimPlex],order=[2,1]),BMat))),MatA)
|
shape=[1_pPETSCINT,dimPlex**2],order=[2,1]),BMat))),MatA)
|
||||||
MatB = MatB &
|
MatB = MatB &
|
||||||
+ matmul(reshape(homogenization_F(1:dimPlex,1:dimPlex,m),shape=[1,dimPlex*dimPlex]),MatA)
|
+ matmul(reshape(homogenization_F(1:dimPlex,1:dimPlex,m),shape=[1_pPETSCINT,dimPlex**2]),MatA)
|
||||||
FAvg = FAvg + F
|
FAvg = FAvg + F
|
||||||
BMatAvg = BMatAvg + BMat
|
BMatAvg = BMatAvg + BMat
|
||||||
else
|
else
|
||||||
|
@ -546,39 +571,40 @@ subroutine FEM_mechanical_formJacobian(dm_local,xx_local,Jac_pre,Jac,dummy,ierr)
|
||||||
FInv = math_inv33(FAvg)
|
FInv = math_inv33(FAvg)
|
||||||
K_e = K_eA*math_det33(FAvg/real(nQuadrature))**(1.0/real(dimPlex)) + &
|
K_e = K_eA*math_det33(FAvg/real(nQuadrature))**(1.0/real(dimPlex)) + &
|
||||||
(matmul(matmul(transpose(BMatAvg), &
|
(matmul(matmul(transpose(BMatAvg), &
|
||||||
reshape(FInv(1:dimPlex,1:dimPlex),shape=[dimPlex*dimPlex,1],order=[2,1])),MatB) + &
|
reshape(FInv(1:dimPlex,1:dimPlex),shape=[dimPlex**2,1_pPETSCINT],order=[2,1])),MatB) + &
|
||||||
K_eB)/real(dimPlex)
|
K_eB)/real(dimPlex)
|
||||||
else
|
else
|
||||||
K_e = K_eA
|
K_e = K_eA
|
||||||
endif
|
endif
|
||||||
K_e = (K_e + eps*math_eye(cellDof)) * abs(detJ)
|
K_e = (K_e + eps*math_eye(int(cellDof))) * abs(detJ)
|
||||||
#ifndef __INTEL_COMPILER
|
#ifndef __INTEL_COMPILER
|
||||||
pK_e(1:cellDOF**2) => K_e
|
pK_e(1:cellDOF**2) => K_e
|
||||||
#else
|
#else
|
||||||
! https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/782230 (bug)
|
! https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/782230 (bug)
|
||||||
allocate(pK_e(cellDOF**2),source = reshape(K_e,[cellDOF**2]))
|
allocate(pK_e(cellDOF**2),source = reshape(K_e,[cellDOF**2]))
|
||||||
#endif
|
#endif
|
||||||
call DMPlexMatSetClosure(dm_local,section,gSection,Jac,cell,pK_e,ADD_VALUES,ierr)
|
call DMPlexMatSetClosure(dm_local,section,gSection,Jac,cell,pK_e,ADD_VALUES,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMPlexVecRestoreClosure(dm_local,section,x_local,cell,x_scal,ierr)
|
call DMPlexVecRestoreClosure(dm_local,section,x_local,cell,x_scal,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
enddo
|
enddo
|
||||||
call MatAssemblyBegin(Jac,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
call MatAssemblyBegin(Jac,MAT_FINAL_ASSEMBLY,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call MatAssemblyEnd(Jac,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
call MatAssemblyEnd(Jac,MAT_FINAL_ASSEMBLY,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call MatAssemblyBegin(Jac_pre,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
call MatAssemblyBegin(Jac_pre,MAT_FINAL_ASSEMBLY,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call MatAssemblyEnd(Jac_pre,MAT_FINAL_ASSEMBLY,ierr); CHKERRQ(ierr)
|
call MatAssemblyEnd(Jac_pre,MAT_FINAL_ASSEMBLY,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMRestoreLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
call DMRestoreLocalVector(dm_local,x_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! apply boundary conditions
|
! apply boundary conditions
|
||||||
#if (PETSC_VERSION_MINOR < 14)
|
#if (PETSC_VERSION_MINOR < 14)
|
||||||
call DMPlexCreateRigidBody(dm_local,matnull,ierr); CHKERRQ(ierr)
|
call DMPlexCreateRigidBody(dm_local,matnull,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
#else
|
#else
|
||||||
call DMPlexCreateRigidBody(dm_local,0,matnull,ierr); CHKERRQ(ierr)
|
call DMPlexCreateRigidBody(dm_local,0_pPETSCINT,matnull,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
#endif
|
#endif
|
||||||
call MatSetNullSpace(Jac,matnull,ierr); CHKERRQ(ierr)
|
call MatSetNullSpace(Jac,matnull,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call MatSetNearNullSpace(Jac,matnull,ierr); CHKERRQ(ierr)
|
call MatSetNearNullSpace(Jac,matnull,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call MatNullSpaceDestroy(matnull,ierr); CHKERRQ(ierr)
|
call MatNullSpaceDestroy(matnull,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine FEM_mechanical_formJacobian
|
end subroutine FEM_mechanical_formJacobian
|
||||||
|
|
||||||
|
@ -601,43 +627,43 @@ subroutine FEM_mechanical_forward(guess,timeinc,timeinc_old,fieldBC)
|
||||||
Vec :: x_local
|
Vec :: x_local
|
||||||
PetscSection :: section
|
PetscSection :: section
|
||||||
IS :: bcPoints
|
IS :: bcPoints
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! forward last inc
|
! forward last inc
|
||||||
if (guess .and. .not. cutBack) then
|
if (guess .and. .not. cutBack) then
|
||||||
ForwardData = .True.
|
ForwardData = .True.
|
||||||
homogenization_F0 = homogenization_F
|
homogenization_F0 = homogenization_F
|
||||||
call SNESGetDM(mechanical_snes,dm_local,ierr); CHKERRQ(ierr) !< retrieve mesh info from mechanical_snes into dm_local
|
call SNESGetDM(mechanical_snes,dm_local,err_PETSc); CHKERRQ(err_PETSc) !< retrieve mesh info from mechanical_snes into dm_local
|
||||||
call DMGetSection(dm_local,section,ierr); CHKERRQ(ierr)
|
call DMGetSection(dm_local,section,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGetLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
call DMGetLocalVector(dm_local,x_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call VecSet(x_local,0.0_pReal,ierr); CHKERRQ(ierr)
|
call VecSet(x_local,0.0_pReal,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGlobalToLocalBegin(dm_local,solution,INSERT_VALUES,x_local,ierr) !< retrieve my partition of global solution vector
|
call DMGlobalToLocalBegin(dm_local,solution,INSERT_VALUES,x_local,err_PETSc) !< retrieve my partition of global solution vector
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call DMGlobalToLocalEnd(dm_local,solution,INSERT_VALUES,x_local,ierr)
|
call DMGlobalToLocalEnd(dm_local,solution,INSERT_VALUES,x_local,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call VecAXPY(solution_local,1.0,x_local,ierr); CHKERRQ(ierr)
|
call VecAXPY(solution_local,1.0,x_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
do field = 1, dimPlex; do face = 1, mesh_Nboundaries
|
do field = 1, dimPlex; do face = 1, mesh_Nboundaries
|
||||||
if (fieldBC%componentBC(field)%Mask(face)) then
|
if (fieldBC%componentBC(field)%Mask(face)) then
|
||||||
call DMGetStratumSize(dm_local,'Face Sets',mesh_boundaries(face),bcSize,ierr)
|
call DMGetStratumSize(dm_local,'Face Sets',mesh_boundaries(face),bcSize,err_PETSc)
|
||||||
if (bcSize > 0) then
|
if (bcSize > 0) then
|
||||||
call DMGetStratumIS(dm_local,'Face Sets',mesh_boundaries(face),bcPoints,ierr)
|
call DMGetStratumIS(dm_local,'Face Sets',mesh_boundaries(face),bcPoints,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
call utilities_projectBCValues(solution_local,section,0,field-1,bcPoints, &
|
call utilities_projectBCValues(solution_local,section,0_pPETSCINT,field-1,bcPoints, &
|
||||||
0.0_pReal,fieldBC%componentBC(field)%Value(face),timeinc_old)
|
0.0_pReal,fieldBC%componentBC(field)%Value(face),timeinc_old)
|
||||||
call ISDestroy(bcPoints,ierr); CHKERRQ(ierr)
|
call ISDestroy(bcPoints,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
enddo; enddo
|
enddo; enddo
|
||||||
call DMRestoreLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
call DMRestoreLocalVector(dm_local,x_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! update rate and forward last inc
|
! update rate and forward last inc
|
||||||
call VecCopy(solution,solution_rate,ierr); CHKERRQ(ierr)
|
call VecCopy(solution,solution_rate,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call VecScale(solution_rate,1.0/timeinc_old,ierr); CHKERRQ(ierr)
|
call VecScale(solution_rate,1.0/timeinc_old,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
endif
|
endif
|
||||||
call VecCopy(solution_rate,solution,ierr); CHKERRQ(ierr)
|
call VecCopy(solution_rate,solution,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call VecScale(solution,timeinc,ierr); CHKERRQ(ierr)
|
call VecScale(solution,timeinc,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine FEM_mechanical_forward
|
end subroutine FEM_mechanical_forward
|
||||||
|
|
||||||
|
@ -645,24 +671,24 @@ end subroutine FEM_mechanical_forward
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
!> @brief reporting
|
!> @brief reporting
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine FEM_mechanical_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dummy,ierr)
|
subroutine FEM_mechanical_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dummy,err_PETSc)
|
||||||
|
|
||||||
SNES :: snes_local
|
SNES :: snes_local
|
||||||
PetscInt :: PETScIter
|
PetscInt :: PETScIter
|
||||||
PetscReal :: xnorm,snorm,fnorm,divTol
|
PetscReal :: xnorm,snorm,fnorm,divTol
|
||||||
SNESConvergedReason :: reason
|
SNESConvergedReason :: reason
|
||||||
PetscObject :: dummy
|
PetscObject :: dummy
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! report
|
! report
|
||||||
divTol = max(maxval(abs(P_av(1:dimPlex,1:dimPlex)))*num%eps_struct_rtol,num%eps_struct_atol)
|
divTol = max(maxval(abs(P_av(1:dimPlex,1:dimPlex)))*num%eps_struct_rtol,num%eps_struct_atol)
|
||||||
call SNESConvergedDefault(snes_local,PETScIter,xnorm,snorm,fnorm/divTol,reason,dummy,ierr)
|
call SNESConvergedDefault(snes_local,PETScIter,xnorm,snorm,fnorm/divTol,reason,dummy,err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
if (terminallyIll) reason = SNES_DIVERGED_FUNCTION_DOMAIN
|
if (terminallyIll) reason = SNES_DIVERGED_FUNCTION_DOMAIN
|
||||||
print'(/,1x,a,a,i0,a,i0,f0.3)', trim(incInfo), &
|
print'(/,1x,a,a,i0,a,i0,f0.3)', trim(incInfo), &
|
||||||
' @ Iteration ',PETScIter,' mechanical residual norm = ', &
|
' @ Iteration ',PETScIter,' mechanical residual norm = ', &
|
||||||
int(fnorm/divTol),fnorm/divTol-int(fnorm/divTol)
|
int(fnorm/divTol),fnorm/divTol-int(fnorm/divTol) ! ToDo: int casting?
|
||||||
print'(/,1x,a,/,2(3(2x,f12.4,1x)/),3(2x,f12.4,1x))', &
|
print'(/,1x,a,/,2(3(2x,f12.4,1x)/),3(2x,f12.4,1x))', &
|
||||||
'Piola--Kirchhoff stress / MPa =',transpose(P_av)*1.e-6_pReal
|
'Piola--Kirchhoff stress / MPa =',transpose(P_av)*1.e-6_pReal
|
||||||
flush(IO_STDOUT)
|
flush(IO_STDOUT)
|
||||||
|
@ -675,9 +701,7 @@ end subroutine FEM_mechanical_converged
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine FEM_mechanical_updateCoords()
|
subroutine FEM_mechanical_updateCoords()
|
||||||
|
|
||||||
real(pReal), pointer, dimension(:) :: &
|
PetscReal, pointer, dimension(:,:) :: &
|
||||||
nodeCoords_linear !< nodal coordinates (dimPlex*Nnodes)
|
|
||||||
real(pReal), pointer, dimension(:,:) :: &
|
|
||||||
nodeCoords !< nodal coordinates (3,Nnodes)
|
nodeCoords !< nodal coordinates (3,Nnodes)
|
||||||
real(pReal), pointer, dimension(:,:,:) :: &
|
real(pReal), pointer, dimension(:,:,:) :: &
|
||||||
ipCoords !< ip coordinates (3,nQuadrature,mesh_NcpElems)
|
ipCoords !< ip coordinates (3,nQuadrature,mesh_NcpElems)
|
||||||
|
@ -690,39 +714,44 @@ subroutine FEM_mechanical_updateCoords()
|
||||||
|
|
||||||
DM :: dm_local
|
DM :: dm_local
|
||||||
Vec :: x_local
|
Vec :: x_local
|
||||||
PetscErrorCode :: ierr
|
PetscErrorCode :: err_PETSc
|
||||||
PetscInt :: pStart, pEnd, p, s, e, q, &
|
PetscInt :: pStart, pEnd, p, s, e, q, &
|
||||||
cellStart, cellEnd, c, n
|
cellStart, cellEnd, c, n
|
||||||
PetscSection :: section
|
PetscSection :: section
|
||||||
PetscQuadrature :: mechQuad
|
PetscQuadrature :: mechQuad
|
||||||
PetscReal, dimension(:), pointer :: basisField, basisFieldDer
|
PetscReal, dimension(:), pointer :: basisField, basisFieldDer, &
|
||||||
|
nodeCoords_linear !< nodal coordinates (dimPlex*Nnodes)
|
||||||
PetscScalar, dimension(:), pointer :: x_scal
|
PetscScalar, dimension(:), pointer :: x_scal
|
||||||
|
|
||||||
call SNESGetDM(mechanical_snes,dm_local,ierr); CHKERRQ(ierr)
|
call SNESGetDM(mechanical_snes,dm_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGetDS(dm_local,mechQuad,ierr); CHKERRQ(ierr)
|
call DMGetDS(dm_local,mechQuad,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGetLocalSection(dm_local,section,ierr); CHKERRQ(ierr)
|
call DMGetLocalSection(dm_local,section,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGetLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
call DMGetLocalVector(dm_local,x_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
call DMGetDimension(dm_local,dimPlex,ierr); CHKERRQ(ierr)
|
call DMGetDimension(dm_local,dimPlex,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
! write cell vertex displacements
|
! write cell vertex displacements
|
||||||
call DMPlexGetDepthStratum(dm_local,0,pStart,pEnd,ierr); CHKERRQ(ierr)
|
call DMPlexGetDepthStratum(dm_local,0_pPETSCINT,pStart,pEnd,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
allocate(nodeCoords(3,pStart:pEnd-1),source=0.0_pReal)
|
allocate(nodeCoords(3,pStart:pEnd-1),source=0.0_pReal)
|
||||||
call VecGetArrayF90(x_local,nodeCoords_linear,ierr); CHKERRQ(ierr)
|
call VecGetArrayF90(x_local,nodeCoords_linear,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
do p=pStart, pEnd-1
|
do p=pStart, pEnd-1
|
||||||
call DMPlexGetPointLocal(dm_local, p, s, e, ierr); CHKERRQ(ierr)
|
call DMPlexGetPointLocal(dm_local, p, s, e, err_PETSc); CHKERRQ(err_PETSc)
|
||||||
nodeCoords(1:dimPlex,p)=nodeCoords_linear(s+1:e)
|
nodeCoords(1:dimPlex,p)=nodeCoords_linear(s+1:e)
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
call discretization_setNodeCoords(nodeCoords)
|
call discretization_setNodeCoords(nodeCoords)
|
||||||
call VecRestoreArrayF90(x_local,nodeCoords_linear,ierr); CHKERRQ(ierr)
|
call VecRestoreArrayF90(x_local,nodeCoords_linear,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
! write ip displacements
|
! write ip displacements
|
||||||
call DMPlexGetHeightStratum(dm_local,0,cellStart,cellEnd,ierr); CHKERRQ(ierr)
|
call DMPlexGetHeightStratum(dm_local,0_pPETSCINT,cellStart,cellEnd,err_PETSc)
|
||||||
call PetscDSGetTabulation(mechQuad,0,basisField,basisFieldDer,ierr); CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
call PetscDSGetTabulation(mechQuad,0_pPETSCINT,basisField,basisFieldDer,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
allocate(ipCoords(3,nQuadrature,mesh_NcpElems),source=0.0_pReal)
|
allocate(ipCoords(3,nQuadrature,mesh_NcpElems),source=0.0_pReal)
|
||||||
do c=cellStart,cellEnd-1
|
do c=cellStart,cellEnd-1
|
||||||
qOffset=0
|
qOffset=0
|
||||||
call DMPlexVecGetClosure(dm_local,section,x_local,c,x_scal,ierr); CHKERRQ(ierr) !< get nodal coordinates of each element
|
call DMPlexVecGetClosure(dm_local,section,x_local,c,x_scal,err_PETSc) !< get nodal coordinates of each element
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
do qPt=0,nQuadrature-1
|
do qPt=0,nQuadrature-1
|
||||||
qOffset= qPt * (size(basisField)/nQuadrature)
|
qOffset= qPt * (size(basisField)/nQuadrature)
|
||||||
do comp=0,dimPlex-1 !< loop over components
|
do comp=0,dimPlex-1 !< loop over components
|
||||||
|
@ -737,10 +766,11 @@ subroutine FEM_mechanical_updateCoords()
|
||||||
enddo
|
enddo
|
||||||
enddo
|
enddo
|
||||||
enddo
|
enddo
|
||||||
call DMPlexVecRestoreClosure(dm_local,section,x_local,c,x_scal,ierr); CHKERRQ(ierr)
|
call DMPlexVecRestoreClosure(dm_local,section,x_local,c,x_scal,err_PETSc)
|
||||||
|
CHKERRQ(err_PETSc)
|
||||||
end do
|
end do
|
||||||
call discretization_setIPcoords(reshape(ipCoords,[3,mesh_NcpElems*nQuadrature]))
|
call discretization_setIPcoords(reshape(ipCoords,[3,mesh_NcpElems*nQuadrature]))
|
||||||
call DMRestoreLocalVector(dm_local,x_local,ierr); CHKERRQ(ierr)
|
call DMRestoreLocalVector(dm_local,x_local,err_PETSc); CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
end subroutine FEM_mechanical_updateCoords
|
end subroutine FEM_mechanical_updateCoords
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,17 @@ module parallelization
|
||||||
implicit none
|
implicit none
|
||||||
private
|
private
|
||||||
|
|
||||||
integer, protected, public :: &
|
#ifndef PETSC
|
||||||
worldrank = 0, & !< MPI worldrank (/=0 for MPI simulations only)
|
integer, parameter, public :: &
|
||||||
worldsize = 1 !< MPI worldsize (/=1 for MPI simulations only)
|
MPI_INTEGER_KIND = pI64
|
||||||
|
integer(MPI_INTEGER_KIND), parameter, public :: &
|
||||||
|
worldrank = 0_MPI_INTEGER_KIND, & !< MPI dummy worldrank
|
||||||
|
worldsize = 1_MPI_INTEGER_KIND !< MPI dummy worldsize
|
||||||
|
#else
|
||||||
|
integer(MPI_INTEGER_KIND), protected, public :: &
|
||||||
|
worldrank = 0_MPI_INTEGER_KIND, & !< MPI worldrank (/=0 for MPI simulations only)
|
||||||
|
worldsize = 1_MPI_INTEGER_KIND !< MPI worldsize (/=1 for MPI simulations only)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PETSC
|
#ifndef PETSC
|
||||||
public :: parallelization_bcast_str
|
public :: parallelization_bcast_str
|
||||||
|
@ -44,54 +52,68 @@ contains
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
subroutine parallelization_init
|
subroutine parallelization_init
|
||||||
|
|
||||||
integer :: err, typeSize
|
integer(MPI_INTEGER_KIND) :: err_MPI, typeSize
|
||||||
|
character(len=4) :: rank_str
|
||||||
!$ integer :: got_env, threadLevel
|
!$ integer :: got_env, threadLevel
|
||||||
!$ integer(pI32) :: OMP_NUM_THREADS
|
!$ integer(pI32) :: OMP_NUM_THREADS
|
||||||
!$ character(len=6) NumThreadsString
|
!$ character(len=6) NumThreadsString
|
||||||
|
|
||||||
|
|
||||||
PetscErrorCode :: petsc_err
|
PetscErrorCode :: err_PETSc
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
! If openMP is enabled, check if the MPI libary supports it and initialize accordingly.
|
! If openMP is enabled, check if the MPI libary supports it and initialize accordingly.
|
||||||
! Otherwise, the first call to PETSc will do the initialization.
|
! Otherwise, the first call to PETSc will do the initialization.
|
||||||
call MPI_Init_Thread(MPI_THREAD_FUNNELED,threadLevel,err)
|
call MPI_Init_Thread(MPI_THREAD_FUNNELED,threadLevel,err_MPI)
|
||||||
if (err /= 0) error stop 'MPI init failed'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI init failed'
|
||||||
if (threadLevel<MPI_THREAD_FUNNELED) error stop 'MPI library does not support OpenMP'
|
if (threadLevel<MPI_THREAD_FUNNELED) error stop 'MPI library does not support OpenMP'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
call PetscInitialize(PETSC_NULL_CHARACTER,petsc_err)
|
call PetscInitialize(PETSC_NULL_CHARACTER,err_PETSc)
|
||||||
#else
|
#else
|
||||||
call PetscInitializeNoArguments(petsc_err)
|
call PetscInitializeNoArguments(err_PETSc)
|
||||||
#endif
|
#endif
|
||||||
CHKERRQ(petsc_err)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
#if defined(DEBUG) && defined(__INTEL_COMPILER)
|
#if defined(DEBUG) && defined(__INTEL_COMPILER)
|
||||||
call PetscSetFPTrap(PETSC_FP_TRAP_ON,petsc_err)
|
call PetscSetFPTrap(PETSC_FP_TRAP_ON,err_PETSc)
|
||||||
#else
|
#else
|
||||||
call PetscSetFPTrap(PETSC_FP_TRAP_OFF,petsc_err)
|
call PetscSetFPTrap(PETSC_FP_TRAP_OFF,err_PETSc)
|
||||||
#endif
|
#endif
|
||||||
CHKERRQ(petsc_err)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
call MPI_Comm_rank(MPI_COMM_WORLD,worldrank,err)
|
call MPI_Comm_rank(MPI_COMM_WORLD,worldrank,err_MPI)
|
||||||
if (err /= 0) error stop 'Could not determine worldrank'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) &
|
||||||
|
error stop 'Could not determine worldrank'
|
||||||
|
|
||||||
if (worldrank == 0) print'(/,1x,a)', '<<<+- parallelization init -+>>>'
|
if (worldrank == 0) print'(/,1x,a)', '<<<+- parallelization init -+>>>'
|
||||||
|
|
||||||
call MPI_Comm_size(MPI_COMM_WORLD,worldsize,err)
|
call MPI_Comm_size(MPI_COMM_WORLD,worldsize,err_MPI)
|
||||||
if (err /= 0) error stop 'Could not determine worldsize'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) &
|
||||||
|
error stop 'Could not determine worldsize'
|
||||||
if (worldrank == 0) print'(/,1x,a,i3)', 'MPI processes: ',worldsize
|
if (worldrank == 0) print'(/,1x,a,i3)', 'MPI processes: ',worldsize
|
||||||
|
|
||||||
call MPI_Type_size(MPI_INTEGER,typeSize,err)
|
call MPI_Type_size(MPI_INTEGER,typeSize,err_MPI)
|
||||||
if (err /= 0) error stop 'Could not determine MPI integer size'
|
if (err_MPI /= 0_MPI_INTEGER_KIND) &
|
||||||
if (typeSize*8 /= bit_size(0)) error stop 'Mismatch between MPI and DAMASK integer'
|
error stop 'Could not determine size of MPI_INTEGER'
|
||||||
|
if (typeSize*8_MPI_INTEGER_KIND /= int(bit_size(0),MPI_INTEGER_KIND)) &
|
||||||
|
error stop 'Mismatch between MPI_INTEGER and DAMASK default integer'
|
||||||
|
|
||||||
call MPI_Type_size(MPI_DOUBLE,typeSize,err)
|
call MPI_Type_size(MPI_INTEGER8,typeSize,err_MPI)
|
||||||
if (err /= 0) error stop 'Could not determine MPI real size'
|
if (err_MPI /= 0) &
|
||||||
if (typeSize*8 /= storage_size(0.0_pReal)) error stop 'Mismatch between MPI and DAMASK real'
|
error stop 'Could not determine size of MPI_INTEGER8'
|
||||||
|
if (typeSize*8_MPI_INTEGER_KIND /= int(bit_size(0_pI64),MPI_INTEGER_KIND)) &
|
||||||
|
error stop 'Mismatch between MPI_INTEGER8 and DAMASK pI64'
|
||||||
|
|
||||||
|
call MPI_Type_size(MPI_DOUBLE,typeSize,err_MPI)
|
||||||
|
if (err_MPI /= 0_MPI_INTEGER_KIND) &
|
||||||
|
error stop 'Could not determine size of MPI_DOUBLE'
|
||||||
|
if (typeSize*8_MPI_INTEGER_KIND /= int(storage_size(0.0_pReal),MPI_INTEGER_KIND)) &
|
||||||
|
error stop 'Mismatch between MPI_DOUBLE and DAMASK pReal'
|
||||||
|
|
||||||
if (worldrank /= 0) then
|
if (worldrank /= 0) then
|
||||||
close(OUTPUT_UNIT) ! disable output
|
close(OUTPUT_UNIT) ! disable output
|
||||||
|
write(rank_str,'(i4.4)') worldrank ! use for MPI debug filenames
|
||||||
open(OUTPUT_UNIT,file='/dev/null',status='replace') ! close() alone will leave some temp files in cwd
|
open(OUTPUT_UNIT,file='/dev/null',status='replace') ! close() alone will leave some temp files in cwd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -119,14 +141,14 @@ subroutine parallelization_bcast_str(string)
|
||||||
|
|
||||||
character(len=:), allocatable, intent(inout) :: string
|
character(len=:), allocatable, intent(inout) :: string
|
||||||
|
|
||||||
integer :: strlen, ierr ! pI64 for strlen not supported by MPI
|
integer(MPI_INTEGER_KIND) :: strlen, err_MPI
|
||||||
|
|
||||||
|
|
||||||
if (worldrank == 0) strlen = len(string)
|
if (worldrank == 0) strlen = len(string,MPI_INTEGER_KIND)
|
||||||
call MPI_Bcast(strlen,1,MPI_INTEGER,0,MPI_COMM_WORLD, ierr)
|
call MPI_Bcast(strlen,1_MPI_INTEGER_KIND,MPI_INTEGER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD, err_MPI)
|
||||||
if (worldrank /= 0) allocate(character(len=strlen)::string)
|
if (worldrank /= 0) allocate(character(len=strlen)::string)
|
||||||
|
|
||||||
call MPI_Bcast(string,strlen,MPI_CHARACTER,0,MPI_COMM_WORLD, ierr)
|
call MPI_Bcast(string,strlen,MPI_CHARACTER,0_MPI_INTEGER_KIND,MPI_COMM_WORLD, err_MPI)
|
||||||
|
|
||||||
|
|
||||||
end subroutine parallelization_bcast_str
|
end subroutine parallelization_bcast_str
|
||||||
|
|
|
@ -8,6 +8,7 @@ module phase
|
||||||
use constants
|
use constants
|
||||||
use math
|
use math
|
||||||
use rotations
|
use rotations
|
||||||
|
use polynomials
|
||||||
use IO
|
use IO
|
||||||
use config
|
use config
|
||||||
use material
|
use material
|
||||||
|
|
|
@ -99,11 +99,11 @@ module subroutine thermalexpansion_LiAndItsTangent(Li, dLi_dTstar, ph,me)
|
||||||
associate(prm => param(kinematics_thermal_expansion_instance(ph)))
|
associate(prm => param(kinematics_thermal_expansion_instance(ph)))
|
||||||
Li = dot_T * ( &
|
Li = dot_T * ( &
|
||||||
prm%A(1:3,1:3,1) & ! constant coefficient
|
prm%A(1:3,1:3,1) & ! constant coefficient
|
||||||
+ prm%A(1:3,1:3,2)*(T - prm%T_ref)**1 & ! linear coefficient
|
+ prm%A(1:3,1:3,2)*(T - prm%T_ref) & ! linear coefficient
|
||||||
+ prm%A(1:3,1:3,3)*(T - prm%T_ref)**2 & ! quadratic coefficient
|
+ prm%A(1:3,1:3,3)*(T - prm%T_ref)**2 & ! quadratic coefficient
|
||||||
) / &
|
) / &
|
||||||
(1.0_pReal &
|
(1.0_pReal &
|
||||||
+ prm%A(1:3,1:3,1)*(T - prm%T_ref)**1 / 1.0_pReal &
|
+ prm%A(1:3,1:3,1)*(T - prm%T_ref) / 1.0_pReal &
|
||||||
+ prm%A(1:3,1:3,2)*(T - prm%T_ref)**2 / 2.0_pReal &
|
+ prm%A(1:3,1:3,2)*(T - prm%T_ref)**2 / 2.0_pReal &
|
||||||
+ prm%A(1:3,1:3,3)*(T - prm%T_ref)**3 / 3.0_pReal &
|
+ prm%A(1:3,1:3,3)*(T - prm%T_ref)**3 / 3.0_pReal &
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
submodule(phase:mechanical) elastic
|
submodule(phase:mechanical) elastic
|
||||||
|
|
||||||
type :: tParameters
|
type :: tParameters
|
||||||
real(pReal),dimension(3) :: &
|
type(tPolynomial) :: &
|
||||||
C_11 = 0.0_pReal, &
|
C_11, &
|
||||||
C_12 = 0.0_pReal, &
|
C_12, &
|
||||||
C_13 = 0.0_pReal, &
|
C_13, &
|
||||||
C_33 = 0.0_pReal, &
|
C_33, &
|
||||||
C_44 = 0.0_pReal, &
|
C_44, &
|
||||||
C_66 = 0.0_pReal
|
C_66
|
||||||
real(pReal) :: &
|
|
||||||
T_ref
|
|
||||||
end type tParameters
|
end type tParameters
|
||||||
|
|
||||||
type(tParameters), allocatable, dimension(:) :: param
|
type(tParameters), allocatable, dimension(:) :: param
|
||||||
|
@ -47,35 +45,17 @@ module subroutine elastic_init(phases)
|
||||||
|
|
||||||
associate(prm => param(ph))
|
associate(prm => param(ph))
|
||||||
|
|
||||||
prm%T_ref = elastic%get_asFloat('T_ref', defaultVal=T_ROOM)
|
prm%C_11 = polynomial(elastic%asDict(),'C_11','T')
|
||||||
|
prm%C_12 = polynomial(elastic%asDict(),'C_12','T')
|
||||||
prm%C_11(1) = elastic%get_asFloat('C_11')
|
prm%C_44 = polynomial(elastic%asDict(),'C_44','T')
|
||||||
prm%C_11(2) = elastic%get_asFloat('C_11,T', defaultVal=0.0_pReal)
|
|
||||||
prm%C_11(3) = elastic%get_asFloat('C_11,T^2',defaultVal=0.0_pReal)
|
|
||||||
|
|
||||||
prm%C_12(1) = elastic%get_asFloat('C_12')
|
|
||||||
prm%C_12(2) = elastic%get_asFloat('C_12,T', defaultVal=0.0_pReal)
|
|
||||||
prm%C_12(3) = elastic%get_asFloat('C_12,T^2',defaultVal=0.0_pReal)
|
|
||||||
|
|
||||||
prm%C_44(1) = elastic%get_asFloat('C_44')
|
|
||||||
prm%C_44(2) = elastic%get_asFloat('C_44,T', defaultVal=0.0_pReal)
|
|
||||||
prm%C_44(3) = elastic%get_asFloat('C_44,T^2',defaultVal=0.0_pReal)
|
|
||||||
|
|
||||||
if (any(phase_lattice(ph) == ['hP','tI'])) then
|
if (any(phase_lattice(ph) == ['hP','tI'])) then
|
||||||
prm%C_13(1) = elastic%get_asFloat('C_13')
|
prm%C_13 = polynomial(elastic%asDict(),'C_13','T')
|
||||||
prm%C_13(2) = elastic%get_asFloat('C_13,T', defaultVal=0.0_pReal)
|
prm%C_33 = polynomial(elastic%asDict(),'C_33','T')
|
||||||
prm%C_13(3) = elastic%get_asFloat('C_13,T^2',defaultVal=0.0_pReal)
|
|
||||||
|
|
||||||
prm%C_33(1) = elastic%get_asFloat('C_33')
|
|
||||||
prm%C_33(2) = elastic%get_asFloat('C_33,T', defaultVal=0.0_pReal)
|
|
||||||
prm%C_33(3) = elastic%get_asFloat('C_33,T^2',defaultVal=0.0_pReal)
|
|
||||||
end if
|
end if
|
||||||
|
|
||||||
if (phase_lattice(ph) == 'tI') then
|
if (phase_lattice(ph) == 'tI') &
|
||||||
prm%C_66(1) = elastic%get_asFloat('C_66')
|
prm%C_66 = polynomial(elastic%asDict(),'C_66','T')
|
||||||
prm%C_66(2) = elastic%get_asFloat('C_66,T', defaultVal=0.0_pReal)
|
|
||||||
prm%C_66(3) = elastic%get_asFloat('C_66,T^2',defaultVal=0.0_pReal)
|
|
||||||
end if
|
|
||||||
|
|
||||||
end associate
|
end associate
|
||||||
end do
|
end do
|
||||||
|
@ -97,38 +77,20 @@ pure module function elastic_C66(ph,en) result(C66)
|
||||||
|
|
||||||
|
|
||||||
associate(prm => param(ph))
|
associate(prm => param(ph))
|
||||||
|
|
||||||
C66 = 0.0_pReal
|
C66 = 0.0_pReal
|
||||||
T = thermal_T(ph,en)
|
T = thermal_T(ph,en)
|
||||||
|
|
||||||
C66(1,1) = prm%C_11(1) &
|
C66(1,1) = prm%C_11%at(T)
|
||||||
+ prm%C_11(2)*(T - prm%T_ref)**1 &
|
C66(1,2) = prm%C_12%at(T)
|
||||||
+ prm%C_11(3)*(T - prm%T_ref)**2
|
C66(4,4) = prm%C_44%at(T)
|
||||||
|
|
||||||
C66(1,2) = prm%C_12(1) &
|
|
||||||
+ prm%C_12(2)*(T - prm%T_ref)**1 &
|
|
||||||
+ prm%C_12(3)*(T - prm%T_ref)**2
|
|
||||||
|
|
||||||
C66(4,4) = prm%C_44(1) &
|
|
||||||
+ prm%C_44(2)*(T - prm%T_ref)**1 &
|
|
||||||
+ prm%C_44(3)*(T - prm%T_ref)**2
|
|
||||||
|
|
||||||
|
|
||||||
if (any(phase_lattice(ph) == ['hP','tI'])) then
|
if (any(phase_lattice(ph) == ['hP','tI'])) then
|
||||||
C66(1,3) = prm%C_13(1) &
|
C66(1,3) = prm%C_13%at(T)
|
||||||
+ prm%C_13(2)*(T - prm%T_ref)**1 &
|
C66(3,3) = prm%C_33%at(T)
|
||||||
+ prm%C_13(3)*(T - prm%T_ref)**2
|
|
||||||
|
|
||||||
C66(3,3) = prm%C_33(1) &
|
|
||||||
+ prm%C_33(2)*(T - prm%T_ref)**1 &
|
|
||||||
+ prm%C_33(3)*(T - prm%T_ref)**2
|
|
||||||
|
|
||||||
end if
|
end if
|
||||||
|
|
||||||
if (phase_lattice(ph) == 'tI') then
|
if (phase_lattice(ph) == 'tI') C66(6,6) = prm%C_66%at(T)
|
||||||
C66(6,6) = prm%C_66(1) &
|
|
||||||
+ prm%C_66(2)*(T - prm%T_ref)**1 &
|
|
||||||
+ prm%C_66(3)*(T - prm%T_ref)**2
|
|
||||||
end if
|
|
||||||
|
|
||||||
C66 = lattice_symmetrize_C66(C66,phase_lattice(ph))
|
C66 = lattice_symmetrize_C66(C66,phase_lattice(ph))
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,17 @@ submodule(phase:plastic) dislotwin
|
||||||
p_sb = 1.0_pReal, & !< p-exponent in shear band velocity
|
p_sb = 1.0_pReal, & !< p-exponent in shear band velocity
|
||||||
q_sb = 1.0_pReal, & !< q-exponent in shear band velocity
|
q_sb = 1.0_pReal, & !< q-exponent in shear band velocity
|
||||||
i_tw = 1.0_pReal, & !< adjustment parameter to calculate MFP for twinning
|
i_tw = 1.0_pReal, & !< adjustment parameter to calculate MFP for twinning
|
||||||
L_tw = 1.0_pReal, & !< Length of twin nuclei in Burgers vectors
|
L_tw = 1.0_pReal, & !< length of twin nuclei in Burgers vectors: TODO unit should be meters
|
||||||
L_tr = 1.0_pReal, & !< Length of trans nuclei in Burgers vectors
|
L_tr = 1.0_pReal, & !< length of trans nuclei in Burgers vectors: TODO unit should be meters
|
||||||
x_c_tw = 1.0_pReal, & !< critical distance for formation of twin nucleus
|
x_c_tw = 1.0_pReal, & !< critical distance for formation of twin nucleus
|
||||||
x_c_tr = 1.0_pReal, & !< critical distance for formation of trans nucleus
|
x_c_tr = 1.0_pReal, & !< critical distance for formation of trans nucleus
|
||||||
V_cs = 1.0_pReal, & !< cross slip volume
|
V_cs = 1.0_pReal, & !< cross slip volume
|
||||||
xi_sb = 1.0_pReal, & !< value for shearband resistance
|
xi_sb = 1.0_pReal, & !< value for shearband resistance
|
||||||
v_sb = 1.0_pReal, & !< value for shearband velocity_0
|
v_sb = 1.0_pReal, & !< value for shearband velocity_0
|
||||||
E_sb = 1.0_pReal, & !< activation energy for shear bands
|
E_sb = 1.0_pReal, & !< activation energy for shear bands
|
||||||
delta_G = 1.0_pReal, & !< Free energy difference between austensite and martensite
|
delta_G = 1.0_pReal, & !< free energy difference between austensite and martensite
|
||||||
i_tr = 1.0_pReal, & !< adjustment parameter to calculate MFP for transformation
|
i_tr = 1.0_pReal, & !< adjustment parameter to calculate MFP for transformation
|
||||||
h = 1.0_pReal, & !< Stack height of hex nucleus
|
h = 1.0_pReal, & !< stack height of hex nucleus
|
||||||
T_ref = T_ROOM, &
|
T_ref = T_ROOM, &
|
||||||
a_cI = 1.0_pReal, &
|
a_cI = 1.0_pReal, &
|
||||||
a_cF = 1.0_pReal
|
a_cF = 1.0_pReal
|
||||||
|
@ -40,14 +40,13 @@ submodule(phase:plastic) dislotwin
|
||||||
Q_sl,& !< activation energy for glide [J] for each slip system
|
Q_sl,& !< activation energy for glide [J] for each slip system
|
||||||
v_0, & !< dislocation velocity prefactor [m/s] for each slip system
|
v_0, & !< dislocation velocity prefactor [m/s] for each slip system
|
||||||
dot_N_0_tw, & !< twin nucleation rate [1/m³s] for each twin system
|
dot_N_0_tw, & !< twin nucleation rate [1/m³s] for each twin system
|
||||||
dot_N_0_tr, & !< trans nucleation rate [1/m³s] for each trans system
|
|
||||||
t_tw, & !< twin thickness [m] for each twin system
|
t_tw, & !< twin thickness [m] for each twin system
|
||||||
i_sl, & !< Adj. parameter for distance between 2 forest dislocations for each slip system
|
i_sl, & !< Adj. parameter for distance between 2 forest dislocations for each slip system
|
||||||
t_tr, & !< martensite lamellar thickness [m] for each trans system
|
t_tr, & !< martensite lamellar thickness [m] for each trans system
|
||||||
p, & !< p-exponent in glide velocity
|
p, & !< p-exponent in glide velocity
|
||||||
q, & !< q-exponent in glide velocity
|
q, & !< q-exponent in glide velocity
|
||||||
r, & !< r-exponent in twin nucleation rate
|
r, & !< exponent in twin nucleation rate
|
||||||
s, & !< s-exponent in trans nucleation rate
|
s, & !< exponent in trans nucleation rate
|
||||||
tau_0, & !< strength due to elements in solid solution
|
tau_0, & !< strength due to elements in solid solution
|
||||||
gamma_char, & !< characteristic shear for twins
|
gamma_char, & !< characteristic shear for twins
|
||||||
B, & !< drag coefficient
|
B, & !< drag coefficient
|
||||||
|
@ -102,11 +101,7 @@ submodule(phase:plastic) dislotwin
|
||||||
Lambda_tr, & !< mean free path between 2 obstacles seen by a growing martensite
|
Lambda_tr, & !< mean free path between 2 obstacles seen by a growing martensite
|
||||||
tau_pass, & !< threshold stress for slip
|
tau_pass, & !< threshold stress for slip
|
||||||
tau_hat_tw, & !< threshold stress for twinning
|
tau_hat_tw, & !< threshold stress for twinning
|
||||||
tau_hat_tr, & !< threshold stress for transformation
|
tau_hat_tr !< threshold stress for transformation
|
||||||
V_tw, & !< volume of a new twin
|
|
||||||
V_tr, & !< volume of a new martensite disc
|
|
||||||
tau_r_tw, & !< stress to bring partials close together (twin)
|
|
||||||
tau_r_tr !< stress to bring partials close together (trans)
|
|
||||||
end type tDislotwinDependentState
|
end type tDislotwinDependentState
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -153,10 +148,10 @@ module function plastic_dislotwin_init() result(myPlasticity)
|
||||||
print'(/,a,i0)', ' # phases: ',count(myPlasticity); flush(IO_STDOUT)
|
print'(/,a,i0)', ' # phases: ',count(myPlasticity); flush(IO_STDOUT)
|
||||||
|
|
||||||
print'(/,1x,a)', 'A. Ma and F. Roters, Acta Materialia 52(12):3603–3612, 2004'
|
print'(/,1x,a)', 'A. Ma and F. Roters, Acta Materialia 52(12):3603–3612, 2004'
|
||||||
print'( 1x,a)', 'https://doi.org/10.1016/j.actamat.2004.04.012'//IO_EOL
|
print'( 1x,a)', 'https://doi.org/10.1016/j.actamat.2004.04.012'
|
||||||
|
|
||||||
print'(/,1x,a)', 'F. Roters et al., Computational Materials Science 39:91–95, 2007'
|
print'(/,1x,a)', 'F. Roters et al., Computational Materials Science 39:91–95, 2007'
|
||||||
print'( 1x,a)', 'https://doi.org/10.1016/j.commatsci.2006.04.014'//IO_EOL
|
print'( 1x,a)', 'https://doi.org/10.1016/j.commatsci.2006.04.014'
|
||||||
|
|
||||||
print'(/,1x,a)', 'S.L. Wong et al., Acta Materialia 118:140–151, 2016'
|
print'(/,1x,a)', 'S.L. Wong et al., Acta Materialia 118:140–151, 2016'
|
||||||
print'( 1x,a)', 'https://doi.org/10.1016/j.actamat.2016.07.032'
|
print'( 1x,a)', 'https://doi.org/10.1016/j.actamat.2016.07.032'
|
||||||
|
@ -306,10 +301,10 @@ module function plastic_dislotwin_init() result(myPlasticity)
|
||||||
prm%b_tr = pl%get_as1dFloat('b_tr')
|
prm%b_tr = pl%get_as1dFloat('b_tr')
|
||||||
prm%b_tr = math_expand(prm%b_tr,prm%N_tr)
|
prm%b_tr = math_expand(prm%b_tr,prm%N_tr)
|
||||||
|
|
||||||
prm%h = pl%get_asFloat('h', defaultVal=0.0_pReal) ! ToDo: How to handle that???
|
prm%h = pl%get_asFloat('h', defaultVal=0.0_pReal) ! ToDo: This is not optional!
|
||||||
prm%i_tr = pl%get_asFloat('i_tr', defaultVal=0.0_pReal) ! ToDo: How to handle that???
|
prm%i_tr = pl%get_asFloat('i_tr', defaultVal=0.0_pReal) ! ToDo: This is not optional!
|
||||||
prm%delta_G = pl%get_asFloat('delta_G')
|
prm%delta_G = pl%get_asFloat('delta_G')
|
||||||
prm%x_c_tr = pl%get_asFloat('x_c_tr', defaultVal=0.0_pReal) ! ToDo: How to handle that???
|
prm%x_c_tr = pl%get_asFloat('x_c_tr', defaultVal=0.0_pReal) ! ToDo: This is not optional!
|
||||||
prm%L_tr = pl%get_asFloat('L_tr')
|
prm%L_tr = pl%get_asFloat('L_tr')
|
||||||
prm%a_cI = pl%get_asFloat('a_cI', defaultVal=0.0_pReal)
|
prm%a_cI = pl%get_asFloat('a_cI', defaultVal=0.0_pReal)
|
||||||
prm%a_cF = pl%get_asFloat('a_cF', defaultVal=0.0_pReal)
|
prm%a_cF = pl%get_asFloat('a_cF', defaultVal=0.0_pReal)
|
||||||
|
@ -324,10 +319,6 @@ module function plastic_dislotwin_init() result(myPlasticity)
|
||||||
prm%a_cI, &
|
prm%a_cI, &
|
||||||
prm%a_cF)
|
prm%a_cF)
|
||||||
|
|
||||||
if (phase_lattice(ph) /= 'cF') then
|
|
||||||
prm%dot_N_0_tr = pl%get_as1dFloat('dot_N_0_tr')
|
|
||||||
prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,prm%N_tr)
|
|
||||||
endif
|
|
||||||
prm%t_tr = pl%get_as1dFloat('t_tr')
|
prm%t_tr = pl%get_as1dFloat('t_tr')
|
||||||
prm%t_tr = math_expand(prm%t_tr,prm%N_tr)
|
prm%t_tr = math_expand(prm%t_tr,prm%N_tr)
|
||||||
prm%s = pl%get_as1dFloat('p_tr',defaultVal=[0.0_pReal])
|
prm%s = pl%get_as1dFloat('p_tr',defaultVal=[0.0_pReal])
|
||||||
|
@ -339,11 +330,8 @@ module function plastic_dislotwin_init() result(myPlasticity)
|
||||||
if ( prm%i_tr < 0.0_pReal) extmsg = trim(extmsg)//' i_tr'
|
if ( prm%i_tr < 0.0_pReal) extmsg = trim(extmsg)//' i_tr'
|
||||||
if (any(prm%t_tr < 0.0_pReal)) extmsg = trim(extmsg)//' t_tr'
|
if (any(prm%t_tr < 0.0_pReal)) extmsg = trim(extmsg)//' t_tr'
|
||||||
if (any(prm%s < 0.0_pReal)) extmsg = trim(extmsg)//' p_tr'
|
if (any(prm%s < 0.0_pReal)) extmsg = trim(extmsg)//' p_tr'
|
||||||
if (phase_lattice(ph) /= 'cF') then
|
|
||||||
if (any(prm%dot_N_0_tr < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tr'
|
|
||||||
end if
|
|
||||||
else transActive
|
else transActive
|
||||||
allocate(prm%s,prm%b_tr,prm%t_tr,prm%dot_N_0_tr,source=emptyRealArray)
|
allocate(prm%s,prm%b_tr,prm%t_tr,source=emptyRealArray)
|
||||||
allocate(prm%h_tr_tr(0,0))
|
allocate(prm%h_tr_tr(0,0))
|
||||||
end if transActive
|
end if transActive
|
||||||
|
|
||||||
|
@ -443,13 +431,9 @@ module function plastic_dislotwin_init() result(myPlasticity)
|
||||||
|
|
||||||
allocate(dst%Lambda_tw (prm%sum_N_tw,Nmembers),source=0.0_pReal)
|
allocate(dst%Lambda_tw (prm%sum_N_tw,Nmembers),source=0.0_pReal)
|
||||||
allocate(dst%tau_hat_tw (prm%sum_N_tw,Nmembers),source=0.0_pReal)
|
allocate(dst%tau_hat_tw (prm%sum_N_tw,Nmembers),source=0.0_pReal)
|
||||||
allocate(dst%tau_r_tw (prm%sum_N_tw,Nmembers),source=0.0_pReal)
|
|
||||||
allocate(dst%V_tw (prm%sum_N_tw,Nmembers),source=0.0_pReal)
|
|
||||||
|
|
||||||
allocate(dst%Lambda_tr (prm%sum_N_tr,Nmembers),source=0.0_pReal)
|
allocate(dst%Lambda_tr (prm%sum_N_tr,Nmembers),source=0.0_pReal)
|
||||||
allocate(dst%tau_hat_tr (prm%sum_N_tr,Nmembers),source=0.0_pReal)
|
allocate(dst%tau_hat_tr (prm%sum_N_tr,Nmembers),source=0.0_pReal)
|
||||||
allocate(dst%tau_r_tr (prm%sum_N_tr,Nmembers),source=0.0_pReal)
|
|
||||||
allocate(dst%V_tr (prm%sum_N_tr,Nmembers),source=0.0_pReal)
|
|
||||||
|
|
||||||
end associate
|
end associate
|
||||||
|
|
||||||
|
@ -656,12 +640,14 @@ module subroutine dislotwin_dotState(Mp,T,ph,en)
|
||||||
dot_gamma_tr
|
dot_gamma_tr
|
||||||
real(pReal) :: &
|
real(pReal) :: &
|
||||||
mu, &
|
mu, &
|
||||||
nu
|
nu, &
|
||||||
|
Gamma
|
||||||
|
|
||||||
associate(prm => param(ph), stt => state(ph), dot => dotState(ph), dst => dependentState(ph))
|
associate(prm => param(ph), stt => state(ph), dot => dotState(ph), dst => dependentState(ph))
|
||||||
|
|
||||||
mu = elastic_mu(ph,en)
|
mu = elastic_mu(ph,en)
|
||||||
nu = elastic_nu(ph,en)
|
nu = elastic_nu(ph,en)
|
||||||
|
Gamma = prm%Gamma_sf(1) + prm%Gamma_sf(2) * (T-prm%T_ref)
|
||||||
|
|
||||||
f_matrix = 1.0_pReal &
|
f_matrix = 1.0_pReal &
|
||||||
- sum(stt%f_tw(1:prm%sum_N_tw,en)) &
|
- sum(stt%f_tw(1:prm%sum_N_tw,en)) &
|
||||||
|
@ -689,8 +675,7 @@ module subroutine dislotwin_dotState(Mp,T,ph,en)
|
||||||
else
|
else
|
||||||
! Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981
|
! Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981
|
||||||
sigma_cl = dot_product(prm%n0_sl(1:3,i),matmul(Mp,prm%n0_sl(1:3,i)))
|
sigma_cl = dot_product(prm%n0_sl(1:3,i),matmul(Mp,prm%n0_sl(1:3,i)))
|
||||||
b_d = merge(24.0_pReal*PI*(1.0_pReal - nu)/(2.0_pReal + nu) &
|
b_d = merge(24.0_pReal*PI*(1.0_pReal - nu)/(2.0_pReal + nu) * Gamma / (mu*prm%b_sl(i)), &
|
||||||
* (prm%Gamma_sf(1) + prm%Gamma_sf(2) * T) / (mu*prm%b_sl(i)), &
|
|
||||||
1.0_pReal, &
|
1.0_pReal, &
|
||||||
prm%ExtendedDislocations)
|
prm%ExtendedDislocations)
|
||||||
v_cl = 2.0_pReal*prm%omega*b_d**2*exp(-prm%Q_cl/(K_B*T)) &
|
v_cl = 2.0_pReal*prm%omega*b_d**2*exp(-prm%Q_cl/(K_B*T)) &
|
||||||
|
@ -742,8 +727,6 @@ module subroutine dislotwin_dependentState(T,ph,en)
|
||||||
real(pReal), dimension(param(ph)%sum_N_tr) :: &
|
real(pReal), dimension(param(ph)%sum_N_tr) :: &
|
||||||
inv_lambda_tr_tr, & !< 1/mean free distance between 2 martensite stacks from different systems seen by a growing martensite
|
inv_lambda_tr_tr, & !< 1/mean free distance between 2 martensite stacks from different systems seen by a growing martensite
|
||||||
f_over_t_tr
|
f_over_t_tr
|
||||||
real(pReal), dimension(:), allocatable :: &
|
|
||||||
x0
|
|
||||||
real(pReal) :: &
|
real(pReal) :: &
|
||||||
mu, &
|
mu, &
|
||||||
nu
|
nu
|
||||||
|
@ -756,7 +739,7 @@ module subroutine dislotwin_dependentState(T,ph,en)
|
||||||
sumf_tw = sum(stt%f_tw(1:prm%sum_N_tw,en))
|
sumf_tw = sum(stt%f_tw(1:prm%sum_N_tw,en))
|
||||||
sumf_tr = sum(stt%f_tr(1:prm%sum_N_tr,en))
|
sumf_tr = sum(stt%f_tr(1:prm%sum_N_tr,en))
|
||||||
|
|
||||||
Gamma = prm%Gamma_sf(1) + prm%Gamma_sf(2) * T
|
Gamma = prm%Gamma_sf(1) + prm%Gamma_sf(2) * (T-prm%T_ref)
|
||||||
|
|
||||||
!* rescaled volume fraction for topology
|
!* rescaled volume fraction for topology
|
||||||
f_over_t_tw = stt%f_tw(1:prm%sum_N_tw,en)/prm%t_tw ! this is per system ...
|
f_over_t_tw = stt%f_tw(1:prm%sum_N_tw,en)/prm%t_tw ! this is per system ...
|
||||||
|
@ -786,16 +769,6 @@ module subroutine dislotwin_dependentState(T,ph,en)
|
||||||
+ 3.0_pReal*prm%b_tr*mu/(prm%L_tr*prm%b_tr) &
|
+ 3.0_pReal*prm%b_tr*mu/(prm%L_tr*prm%b_tr) &
|
||||||
+ prm%h*prm%delta_G/(3.0_pReal*prm%b_tr)
|
+ prm%h*prm%delta_G/(3.0_pReal*prm%b_tr)
|
||||||
|
|
||||||
dst%V_tw(:,en) = (PI/4.0_pReal)*prm%t_tw*dst%Lambda_tw(:,en)**2
|
|
||||||
dst%V_tr(:,en) = (PI/4.0_pReal)*prm%t_tr*dst%Lambda_tr(:,en)**2
|
|
||||||
|
|
||||||
|
|
||||||
x0 = mu*prm%b_tw**2/(Gamma*8.0_pReal*PI)*(2.0_pReal+nu)/(1.0_pReal-nu) ! ToDo: In the paper, this is the Burgers vector for slip
|
|
||||||
dst%tau_r_tw(:,en) = mu*prm%b_tw/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%x_c_tw)+cos(pi/3.0_pReal)/x0)
|
|
||||||
|
|
||||||
x0 = mu*prm%b_tr**2/(Gamma*8.0_pReal*PI)*(2.0_pReal+nu)/(1.0_pReal-nu) ! ToDo: In the paper, this is the Burgers vector for slip
|
|
||||||
dst%tau_r_tr(:,en) = mu*prm%b_tr/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%x_c_tr)+cos(pi/3.0_pReal)/x0)
|
|
||||||
|
|
||||||
end associate
|
end associate
|
||||||
|
|
||||||
end subroutine dislotwin_dependentState
|
end subroutine dislotwin_dependentState
|
||||||
|
@ -959,48 +932,68 @@ pure subroutine kinetics_tw(Mp,T,dot_gamma_sl,ph,en,&
|
||||||
real(pReal), dimension(param(ph)%sum_N_tw), optional, intent(out) :: &
|
real(pReal), dimension(param(ph)%sum_N_tw), optional, intent(out) :: &
|
||||||
ddot_gamma_dtau_tw
|
ddot_gamma_dtau_tw
|
||||||
|
|
||||||
real, dimension(param(ph)%sum_N_tw) :: &
|
real :: &
|
||||||
tau, &
|
tau, tau_r, &
|
||||||
Ndot0, &
|
dot_N_0, &
|
||||||
stressRatio_r, &
|
x0, V, &
|
||||||
ddot_gamma_dtau
|
Gamma, &
|
||||||
|
mu, nu, &
|
||||||
integer :: i,s1,s2
|
P_ncs, dP_ncs_dtau, &
|
||||||
|
P, dP_dtau
|
||||||
|
integer, dimension(2) :: &
|
||||||
|
s
|
||||||
|
integer :: i
|
||||||
|
|
||||||
|
|
||||||
associate(prm => param(ph), stt => state(ph), dst => dependentState(ph))
|
associate(prm => param(ph), stt => state(ph), dst => dependentState(ph))
|
||||||
|
|
||||||
do i = 1, prm%sum_N_tw
|
|
||||||
tau(i) = math_tensordot(Mp,prm%P_tw(1:3,1:3,i))
|
|
||||||
isFCC: if (prm%fccTwinTransNucleation) then
|
isFCC: if (prm%fccTwinTransNucleation) then
|
||||||
s1=prm%fcc_twinNucleationSlipPair(1,i)
|
mu = elastic_mu(ph,en)
|
||||||
s2=prm%fcc_twinNucleationSlipPair(2,i)
|
nu = elastic_nu(ph,en)
|
||||||
if (tau(i) < dst%tau_r_tw(i,en)) then ! ToDo: correct?
|
Gamma = prm%Gamma_sf(1) + prm%Gamma_sf(2) * (T-prm%T_ref)
|
||||||
Ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,en)+stt%rho_dip(s2,en))+&
|
|
||||||
abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,en)+stt%rho_dip(s1,en)))/&
|
do i = 1, prm%sum_N_tw
|
||||||
(prm%L_tw*prm%b_sl(i))*&
|
tau = math_tensordot(Mp,prm%P_tw(1:3,1:3,i))
|
||||||
(1.0_pReal-exp(-prm%V_cs/(K_B*T)*(dst%tau_r_tw(i,en)-tau(i))))
|
x0 = mu*prm%b_tw(i)**2*(2.0_pReal+nu)/(Gamma*8.0_pReal*PI*(1.0_pReal-nu)) ! ToDo: In the paper, the Burgers vector for slip is used
|
||||||
|
tau_r = mu*prm%b_tw(i)/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%x_c_tw)+cos(PI/3.0_pReal)/x0) ! ToDo: In the paper, the Burgers vector for slip is used
|
||||||
|
|
||||||
|
if (tau > tol_math_check .and. tau < tau_r) then
|
||||||
|
P = exp(-(dst%tau_hat_tw(i,en)/tau)**prm%r(i))
|
||||||
|
dP_dTau = prm%r(i) * (dst%tau_hat_tw(i,en)/tau)**prm%r(i)/tau * P
|
||||||
|
|
||||||
|
s = prm%fcc_twinNucleationSlipPair(1:2,i)
|
||||||
|
dot_N_0 = sum(abs(dot_gamma_sl(s(2:1:-1)))*(stt%rho_mob(s,en)+stt%rho_dip(s,en))) &
|
||||||
|
/ (prm%L_tw*prm%b_sl(i))
|
||||||
|
|
||||||
|
P_ncs = 1.0_pReal-exp(-prm%V_cs/(K_B*T)*(tau_r-tau))
|
||||||
|
dP_ncs_dtau = prm%V_cs / (K_B * T) * (P_ncs - 1.0_pReal)
|
||||||
|
|
||||||
|
V = PI/4.0_pReal*dst%Lambda_tw(i,en)**2*prm%t_tw(i)
|
||||||
|
dot_gamma_tw(i) = V*dot_N_0*P_ncs*P
|
||||||
|
if (present(ddot_gamma_dtau_tw)) &
|
||||||
|
ddot_gamma_dtau_tw(i) = V*dot_N_0*(P*dP_ncs_dtau + P_ncs*dP_dtau)
|
||||||
else
|
else
|
||||||
Ndot0=0.0_pReal
|
dot_gamma_tw(i) = 0.0_pReal
|
||||||
|
if (present(ddot_gamma_dtau_tw)) ddot_gamma_dtau_tw(i) = 0.0_pReal
|
||||||
end if
|
end if
|
||||||
else isFCC
|
|
||||||
Ndot0=prm%dot_N_0_tw(i)
|
|
||||||
end if isFCC
|
|
||||||
end do
|
end do
|
||||||
|
|
||||||
significantStress: where(tau > tol_math_check)
|
else isFCC
|
||||||
StressRatio_r = (dst%tau_hat_tw(:,en)/tau)**prm%r
|
do i = 1, prm%sum_N_tw
|
||||||
dot_gamma_tw = prm%gamma_char * dst%V_tw(:,en) * Ndot0*exp(-StressRatio_r)
|
error stop 'not implemented'
|
||||||
ddot_gamma_dtau = (dot_gamma_tw*prm%r/tau)*StressRatio_r
|
tau = math_tensordot(Mp,prm%P_tw(1:3,1:3,i))
|
||||||
else where significantStress
|
if (tau > tol_math_check) then
|
||||||
dot_gamma_tw = 0.0_pReal
|
dot_gamma_tw(i) = 0.0_pReal
|
||||||
ddot_gamma_dtau = 0.0_pReal
|
if (present(ddot_gamma_dtau_tw)) ddot_gamma_dtau_tw(i) = 0.0_pReal
|
||||||
end where significantStress
|
else
|
||||||
|
dot_gamma_tw(i) = 0.0_pReal
|
||||||
|
if (present(ddot_gamma_dtau_tw)) ddot_gamma_dtau_tw(i) = 0.0_pReal
|
||||||
|
end if
|
||||||
|
end do
|
||||||
|
end if isFCC
|
||||||
|
|
||||||
end associate
|
end associate
|
||||||
|
|
||||||
if (present(ddot_gamma_dtau_tw)) ddot_gamma_dtau_tw = ddot_gamma_dtau
|
|
||||||
|
|
||||||
end subroutine kinetics_tw
|
end subroutine kinetics_tw
|
||||||
|
|
||||||
|
|
||||||
|
@ -1029,47 +1022,53 @@ pure subroutine kinetics_tr(Mp,T,dot_gamma_sl,ph,en,&
|
||||||
real(pReal), dimension(param(ph)%sum_N_tr), optional, intent(out) :: &
|
real(pReal), dimension(param(ph)%sum_N_tr), optional, intent(out) :: &
|
||||||
ddot_gamma_dtau_tr
|
ddot_gamma_dtau_tr
|
||||||
|
|
||||||
real, dimension(param(ph)%sum_N_tr) :: &
|
real :: &
|
||||||
tau, &
|
tau, tau_r, &
|
||||||
Ndot0, &
|
dot_N_0, &
|
||||||
stressRatio_s, &
|
x0, V, &
|
||||||
ddot_gamma_dtau
|
Gamma, &
|
||||||
integer :: i,s1,s2
|
mu, nu, &
|
||||||
|
P_ncs, dP_ncs_dtau, &
|
||||||
|
P, dP_dtau
|
||||||
|
integer, dimension(2) :: &
|
||||||
|
s
|
||||||
|
integer :: i
|
||||||
|
|
||||||
|
|
||||||
associate(prm => param(ph), stt => state(ph), dst => dependentState(ph))
|
associate(prm => param(ph), stt => state(ph), dst => dependentState(ph))
|
||||||
|
|
||||||
|
mu = elastic_mu(ph,en)
|
||||||
|
nu = elastic_nu(ph,en)
|
||||||
|
Gamma = prm%Gamma_sf(1) + prm%Gamma_sf(2) * (T-prm%T_ref)
|
||||||
|
|
||||||
do i = 1, prm%sum_N_tr
|
do i = 1, prm%sum_N_tr
|
||||||
tau(i) = math_tensordot(Mp,prm%P_tr(1:3,1:3,i))
|
tau = math_tensordot(Mp,prm%P_tr(1:3,1:3,i))
|
||||||
isFCC: if (prm%fccTwinTransNucleation) then
|
x0 = mu*prm%b_tr(i)**2*(2.0_pReal+nu)/(Gamma*8.0_pReal*PI*(1.0_pReal-nu)) ! ToDo: In the paper, the Burgers vector for slip is used
|
||||||
s1=prm%fcc_twinNucleationSlipPair(1,i)
|
tau_r = mu*prm%b_tr(i)/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%x_c_tr)+cos(PI/3.0_pReal)/x0) ! ToDo: In the paper, the Burgers vector for slip is used
|
||||||
s2=prm%fcc_twinNucleationSlipPair(2,i)
|
|
||||||
if (tau(i) < dst%tau_r_tr(i,en)) then ! ToDo: correct?
|
if (tau > tol_math_check .and. tau < tau_r) then
|
||||||
Ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,en)+stt%rho_dip(s2,en))+&
|
P = exp(-(dst%tau_hat_tr(i,en)/tau)**prm%s(i))
|
||||||
abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,en)+stt%rho_dip(s1,en)))/&
|
dP_dTau = prm%s(i) * (dst%tau_hat_tr(i,en)/tau)**prm%s(i)/tau * P
|
||||||
(prm%L_tr*prm%b_sl(i))*&
|
|
||||||
(1.0_pReal-exp(-prm%V_cs/(K_B*T)*(dst%tau_r_tr(i,en)-tau(i))))
|
s = prm%fcc_twinNucleationSlipPair(1:2,i)
|
||||||
|
dot_N_0 = sum(abs(dot_gamma_sl(s(2:1:-1)))*(stt%rho_mob(s,en)+stt%rho_dip(s,en))) &
|
||||||
|
/ (prm%L_tr*prm%b_sl(i))
|
||||||
|
|
||||||
|
P_ncs = 1.0_pReal-exp(-prm%V_cs/(K_B*T)*(tau_r-tau))
|
||||||
|
dP_ncs_dtau = prm%V_cs / (K_B * T) * (P_ncs - 1.0_pReal)
|
||||||
|
|
||||||
|
V = PI/4.0_pReal*dst%Lambda_tr(i,en)**2*prm%t_tr(i)
|
||||||
|
dot_gamma_tr(i) = V*dot_N_0*P_ncs*P
|
||||||
|
if (present(ddot_gamma_dtau_tr)) &
|
||||||
|
ddot_gamma_dtau_tr(i) = V*dot_N_0*(P*dP_ncs_dtau + P_ncs*dP_dtau)
|
||||||
else
|
else
|
||||||
Ndot0=0.0_pReal
|
dot_gamma_tr(i) = 0.0_pReal
|
||||||
|
if (present(ddot_gamma_dtau_tr)) ddot_gamma_dtau_tr(i) = 0.0_pReal
|
||||||
end if
|
end if
|
||||||
else isFCC
|
|
||||||
Ndot0=prm%dot_N_0_tr(i)
|
|
||||||
end if isFCC
|
|
||||||
end do
|
end do
|
||||||
|
|
||||||
significantStress: where(tau > tol_math_check)
|
|
||||||
StressRatio_s = (dst%tau_hat_tr(:,en)/tau)**prm%s
|
|
||||||
dot_gamma_tr = dst%V_tr(:,en) * Ndot0*exp(-StressRatio_s)
|
|
||||||
ddot_gamma_dtau = (dot_gamma_tr*prm%s/tau)*StressRatio_s
|
|
||||||
else where significantStress
|
|
||||||
dot_gamma_tr = 0.0_pReal
|
|
||||||
ddot_gamma_dtau = 0.0_pReal
|
|
||||||
end where significantStress
|
|
||||||
|
|
||||||
end associate
|
end associate
|
||||||
|
|
||||||
if (present(ddot_gamma_dtau_tr)) ddot_gamma_dtau_tr = ddot_gamma_dtau
|
|
||||||
|
|
||||||
end subroutine kinetics_tr
|
end subroutine kinetics_tr
|
||||||
|
|
||||||
end submodule dislotwin
|
end submodule dislotwin
|
||||||
|
|
|
@ -203,7 +203,7 @@ module function plastic_nonlocal_init() result(myPlasticity)
|
||||||
print'(/,a,i0)', ' # phases: ',Ninstances; flush(IO_STDOUT)
|
print'(/,a,i0)', ' # phases: ',Ninstances; flush(IO_STDOUT)
|
||||||
|
|
||||||
print'(/,1x,a)', 'C. Reuber et al., Acta Materialia 71:333–348, 2014'
|
print'(/,1x,a)', 'C. Reuber et al., Acta Materialia 71:333–348, 2014'
|
||||||
print'( 1x,a)', 'https://doi.org/10.1016/j.actamat.2014.03.012'//IO_EOL
|
print'( 1x,a)', 'https://doi.org/10.1016/j.actamat.2014.03.012'
|
||||||
|
|
||||||
print'(/,1x,a)', 'C. Kords, Dissertation RWTH Aachen, 2014'
|
print'(/,1x,a)', 'C. Kords, Dissertation RWTH Aachen, 2014'
|
||||||
print'( 1x,a)', 'http://publications.rwth-aachen.de/record/229993'
|
print'( 1x,a)', 'http://publications.rwth-aachen.de/record/229993'
|
||||||
|
@ -1570,7 +1570,6 @@ subroutine stateInit(ini,phase,Nentries)
|
||||||
upto, &
|
upto, &
|
||||||
s
|
s
|
||||||
real(pReal), dimension(2) :: &
|
real(pReal), dimension(2) :: &
|
||||||
noise, &
|
|
||||||
rnd
|
rnd
|
||||||
real(pReal) :: &
|
real(pReal) :: &
|
||||||
meanDensity, &
|
meanDensity, &
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @author Martin Diehl, KU Leuven
|
||||||
|
!> @brief Polynomial representation for variable data
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
module polynomials
|
||||||
|
use prec
|
||||||
|
use IO
|
||||||
|
use YAML_parse
|
||||||
|
use YAML_types
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
private
|
||||||
|
|
||||||
|
type, public :: tPolynomial
|
||||||
|
real(pReal), dimension(:), allocatable :: coef
|
||||||
|
real(pReal) :: x_ref
|
||||||
|
contains
|
||||||
|
procedure, public :: at => eval
|
||||||
|
procedure, public :: der1_at => eval_der1
|
||||||
|
end type tPolynomial
|
||||||
|
|
||||||
|
interface polynomial
|
||||||
|
module procedure polynomial_from_dict
|
||||||
|
module procedure polynomial_from_coef
|
||||||
|
end interface polynomial
|
||||||
|
|
||||||
|
public :: &
|
||||||
|
polynomial, &
|
||||||
|
polynomials_init
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @brief Run self-test.
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
subroutine polynomials_init()
|
||||||
|
|
||||||
|
print'(/,1x,a)', '<<<+- polynomials init -+>>>'; flush(IO_STDOUT)
|
||||||
|
|
||||||
|
call selfTest()
|
||||||
|
|
||||||
|
end subroutine polynomials_init
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @brief Initialize a Polynomial from Coefficients.
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
function polynomial_from_coef(coef,x_ref) result(p)
|
||||||
|
|
||||||
|
real(pReal), dimension(:), intent(in) :: coef
|
||||||
|
real(pReal), intent(in) :: x_ref
|
||||||
|
type(tPolynomial) :: p
|
||||||
|
|
||||||
|
|
||||||
|
allocate(p%coef(0:size(coef)-1),source=coef) ! should be zero based
|
||||||
|
p%x_ref = x_ref
|
||||||
|
|
||||||
|
end function polynomial_from_coef
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @brief Initialize a Polynomial from a Dictionary with Coefficients.
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
function polynomial_from_dict(dict,y,x) result(p)
|
||||||
|
|
||||||
|
type(tDict), intent(in) :: dict
|
||||||
|
character(len=*), intent(in) :: y, x
|
||||||
|
type(tPolynomial) :: p
|
||||||
|
|
||||||
|
real(pReal), dimension(:), allocatable :: coef
|
||||||
|
real(pReal) :: x_ref
|
||||||
|
|
||||||
|
|
||||||
|
allocate(coef(1),source=dict%get_asFloat(y))
|
||||||
|
|
||||||
|
if (dict%contains(y//','//x)) then
|
||||||
|
x_ref = dict%get_asFloat(x//'_ref')
|
||||||
|
coef = [coef,dict%get_asFloat(y//','//x)]
|
||||||
|
if (dict%contains(y//','//x//'^2')) then
|
||||||
|
coef = [coef,dict%get_asFloat(y//','//x//'^2')]
|
||||||
|
end if
|
||||||
|
else
|
||||||
|
x_ref = huge(0.0_pReal) ! Simplify debugging
|
||||||
|
end if
|
||||||
|
|
||||||
|
p = Polynomial(coef,x_ref)
|
||||||
|
|
||||||
|
end function polynomial_from_dict
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @brief Evaluate a Polynomial.
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
pure function eval(self,x) result(y)
|
||||||
|
|
||||||
|
class(tPolynomial), intent(in) :: self
|
||||||
|
real(pReal), intent(in) :: x
|
||||||
|
real(pReal) :: y
|
||||||
|
|
||||||
|
integer :: i
|
||||||
|
|
||||||
|
|
||||||
|
y = self%coef(0)
|
||||||
|
do i = 1, ubound(self%coef,1)
|
||||||
|
y = y + self%coef(i) * (x-self%x_ref)**i
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end function eval
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @brief Evaluate a first derivative of Polynomial.
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
pure function eval_der1(self,x) result(y)
|
||||||
|
|
||||||
|
class(tPolynomial), intent(in) :: self
|
||||||
|
real(pReal), intent(in) :: x
|
||||||
|
real(pReal) :: y
|
||||||
|
|
||||||
|
integer :: i
|
||||||
|
|
||||||
|
|
||||||
|
y = 0.0_pReal
|
||||||
|
do i = 1, ubound(self%coef,1)
|
||||||
|
y = y + real(i,pReal)*self%coef(i) * (x-self%x_ref)**(i-1)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end function eval_der1
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
!> @brief Check correctness of polynomical functionality.
|
||||||
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
subroutine selfTest
|
||||||
|
|
||||||
|
type(tPolynomial) :: p1, p2
|
||||||
|
real(pReal), dimension(3) :: coef
|
||||||
|
real(pReal) :: x_ref, x
|
||||||
|
class(tNode), pointer :: dict
|
||||||
|
character(len=pStringLen), dimension(3) :: coef_s
|
||||||
|
character(len=pStringLen) :: x_ref_s, x_s, YAML_s
|
||||||
|
|
||||||
|
call random_number(coef)
|
||||||
|
call random_number(x_ref)
|
||||||
|
call random_number(x)
|
||||||
|
|
||||||
|
coef = coef*10_pReal -0.5_pReal
|
||||||
|
x_ref = x_ref*10_pReal -0.5_pReal
|
||||||
|
x = x*10_pReal -0.5_pReal
|
||||||
|
|
||||||
|
p1 = polynomial(coef,x_ref)
|
||||||
|
if (dNeq(p1%at(x_ref),coef(1))) error stop 'polynomial: @ref'
|
||||||
|
|
||||||
|
write(coef_s(1),*) coef(1)
|
||||||
|
write(coef_s(2),*) coef(2)
|
||||||
|
write(coef_s(3),*) coef(3)
|
||||||
|
write(x_ref_s,*) x_ref
|
||||||
|
write(x_s,*) x
|
||||||
|
YAML_s = 'C: '//trim(adjustl(coef_s(1)))//IO_EOL//&
|
||||||
|
'C,T: '//trim(adjustl(coef_s(2)))//IO_EOL//&
|
||||||
|
'C,T^2: '//trim(adjustl(coef_s(3)))//IO_EOL//&
|
||||||
|
'T_ref: '//trim(adjustl(x_ref_s))//IO_EOL
|
||||||
|
Dict => YAML_parse_str(trim(YAML_s))
|
||||||
|
p2 = polynomial(dict%asDict(),'C','T')
|
||||||
|
if (dNeq(p1%at(x),p2%at(x),1.0e-12_pReal)) error stop 'polynomials: init'
|
||||||
|
|
||||||
|
p1 = polynomial(coef*[0.0_pReal,1.0_pReal,0.0_pReal],x_ref)
|
||||||
|
if (dNeq(p1%at(x_ref+x),-p1%at(x_ref-x),1.0e-10_pReal)) error stop 'polynomials: eval(odd)'
|
||||||
|
if (dNeq(p1%der1_at(x),p1%der1_at(5.0_pReal*x),1.0e-10_pReal)) error stop 'polynomials: eval_der(odd)'
|
||||||
|
|
||||||
|
p1 = polynomial(coef*[0.0_pReal,0.0_pReal,1.0_pReal],x_ref)
|
||||||
|
if (dNeq(p1%at(x_ref+x),p1%at(x_ref-x),1e-10_pReal)) error stop 'polynomials: eval(even)'
|
||||||
|
if (dNeq(p1%der1_at(x_ref+x),-p1%der1_at(x_ref-x),1e-10_pReal)) error stop 'polynomials: eval_der(even)'
|
||||||
|
|
||||||
|
|
||||||
|
end subroutine selfTest
|
||||||
|
|
||||||
|
end module polynomials
|
26
src/prec.f90
26
src/prec.f90
|
@ -10,6 +10,11 @@ module prec
|
||||||
use, intrinsic :: IEEE_arithmetic
|
use, intrinsic :: IEEE_arithmetic
|
||||||
use, intrinsic :: ISO_C_binding
|
use, intrinsic :: ISO_C_binding
|
||||||
|
|
||||||
|
#ifdef PETSC
|
||||||
|
#include <petsc/finclude/petscsys.h>
|
||||||
|
use PETScSys
|
||||||
|
#endif
|
||||||
|
|
||||||
implicit none
|
implicit none
|
||||||
public
|
public
|
||||||
|
|
||||||
|
@ -17,13 +22,12 @@ module prec
|
||||||
integer, parameter :: pReal = IEEE_selected_real_kind(15,307) !< number with 15 significant digits, up to 1e+-307 (typically 64 bit)
|
integer, parameter :: pReal = IEEE_selected_real_kind(15,307) !< number with 15 significant digits, up to 1e+-307 (typically 64 bit)
|
||||||
integer, parameter :: pI32 = selected_int_kind(9) !< number with at least up to +-1e9 (typically 32 bit)
|
integer, parameter :: pI32 = selected_int_kind(9) !< number with at least up to +-1e9 (typically 32 bit)
|
||||||
integer, parameter :: pI64 = selected_int_kind(18) !< number with at least up to +-1e18 (typically 64 bit)
|
integer, parameter :: pI64 = selected_int_kind(18) !< number with at least up to +-1e18 (typically 64 bit)
|
||||||
#if(INT==8)
|
#ifdef PETSC
|
||||||
integer, parameter :: pInt = pI64
|
PetscInt, private :: dummy
|
||||||
#else
|
integer, parameter :: pPETSCINT = kind(dummy)
|
||||||
integer, parameter :: pInt = pI32
|
|
||||||
#endif
|
#endif
|
||||||
integer, parameter :: pStringLen = 256 !< default string length
|
integer, parameter :: pSTRINGLEN = 256 !< default string length
|
||||||
integer, parameter :: pPathLen = 4096 !< maximum length of a path name on linux
|
integer, parameter :: pPATHLEN = 4096 !< maximum length of a path name on linux
|
||||||
|
|
||||||
real(pReal), parameter :: tol_math_check = 1.0e-8_pReal !< tolerance for internal math self-checks (rotation)
|
real(pReal), parameter :: tol_math_check = 1.0e-8_pReal !< tolerance for internal math self-checks (rotation)
|
||||||
|
|
||||||
|
@ -268,7 +272,7 @@ subroutine selfTest
|
||||||
|
|
||||||
integer, allocatable, dimension(:) :: realloc_lhs_test
|
integer, allocatable, dimension(:) :: realloc_lhs_test
|
||||||
real(pReal), dimension(1) :: f
|
real(pReal), dimension(1) :: f
|
||||||
integer(pInt), dimension(1) :: i
|
integer(pI64), dimension(1) :: i
|
||||||
real(pReal), dimension(2) :: r
|
real(pReal), dimension(2) :: r
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,11 +293,11 @@ subroutine selfTest
|
||||||
f = real(prec_bytesToC_DOUBLE(int([0,0,0,-32,+119,+65,+115,65],C_SIGNED_CHAR)),pReal)
|
f = real(prec_bytesToC_DOUBLE(int([0,0,0,-32,+119,+65,+115,65],C_SIGNED_CHAR)),pReal)
|
||||||
if (dNeq(f(1),20191102.0_pReal,0.0_pReal)) error stop 'prec_bytesToC_DOUBLE'
|
if (dNeq(f(1),20191102.0_pReal,0.0_pReal)) error stop 'prec_bytesToC_DOUBLE'
|
||||||
|
|
||||||
i = int(prec_bytesToC_INT32_T(int([+126,+23,+52,+1],C_SIGNED_CHAR)),pInt)
|
i = int(prec_bytesToC_INT32_T(int([+126,+23,+52,+1],C_SIGNED_CHAR)),pI64)
|
||||||
if (i(1) /= 20191102_pInt) error stop 'prec_bytesToC_INT32_T'
|
if (i(1) /= 20191102_pI64) error stop 'prec_bytesToC_INT32_T'
|
||||||
|
|
||||||
i = int(prec_bytesToC_INT64_T(int([+126,+23,+52,+1,0,0,0,0],C_SIGNED_CHAR)),pInt)
|
i = int(prec_bytesToC_INT64_T(int([+126,+23,+52,+1,0,0,0,0],C_SIGNED_CHAR)),pI64)
|
||||||
if (i(1) /= 20191102_pInt) error stop 'prec_bytesToC_INT64_T'
|
if (i(1) /= 20191102_pI64) error stop 'prec_bytesToC_INT64_T'
|
||||||
|
|
||||||
end subroutine selfTest
|
end subroutine selfTest
|
||||||
|
|
||||||
|
|
28
src/quit.f90
28
src/quit.f90
|
@ -15,20 +15,23 @@ subroutine quit(stop_id)
|
||||||
implicit none
|
implicit none
|
||||||
integer, intent(in) :: stop_id
|
integer, intent(in) :: stop_id
|
||||||
integer, dimension(8) :: dateAndTime
|
integer, dimension(8) :: dateAndTime
|
||||||
integer :: error
|
integer :: err_HDF5
|
||||||
PetscErrorCode :: ierr = 0
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
PetscErrorCode :: err_PETSc
|
||||||
|
|
||||||
call h5open_f(error)
|
call h5open_f(err_HDF5)
|
||||||
if (error /= 0) write(6,'(a,i5)') ' Error in h5open_f ',error ! prevents error if not opened yet
|
if (err_HDF5 /= 0_MPI_INTEGER_KIND) write(6,'(a,i5)') ' Error in h5open_f ',err_HDF5 ! prevents error if not opened yet
|
||||||
call h5close_f(error)
|
call h5close_f(err_HDF5)
|
||||||
if (error /= 0) write(6,'(a,i5)') ' Error in h5close_f ',error
|
if (err_HDF5 /= 0_MPI_INTEGER_KIND) write(6,'(a,i5)') ' Error in h5close_f ',err_HDF5
|
||||||
|
|
||||||
call PetscFinalize(ierr)
|
call PetscFinalize(err_PETSc)
|
||||||
CHKERRQ(ierr)
|
CHKERRQ(err_PETSc)
|
||||||
|
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
call MPI_finalize(error)
|
call MPI_finalize(err_MPI)
|
||||||
if (error /= 0) write(6,'(a,i5)') ' Error in MPI_finalize',error
|
if (err_MPI /= 0_MPI_INTEGER_KIND) write(6,'(a,i5)') ' Error in MPI_finalize',err_MPI
|
||||||
|
#else
|
||||||
|
err_MPI = 0_MPI_INTEGER_KIND
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
call date_and_time(values = dateAndTime)
|
call date_and_time(values = dateAndTime)
|
||||||
|
@ -40,7 +43,10 @@ subroutine quit(stop_id)
|
||||||
dateAndTime(6),':',&
|
dateAndTime(6),':',&
|
||||||
dateAndTime(7)
|
dateAndTime(7)
|
||||||
|
|
||||||
if (stop_id == 0 .and. ierr == 0 .and. error == 0) stop 0 ! normal termination
|
if (stop_id == 0 .and. &
|
||||||
|
err_HDF5 == 0 .and. &
|
||||||
|
err_MPI == 0_MPI_INTEGER_KIND .and. &
|
||||||
|
err_PETSC == 0) stop 0 ! normal termination
|
||||||
stop 1 ! error (message from IO_error)
|
stop 1 ! error (message from IO_error)
|
||||||
|
|
||||||
end subroutine quit
|
end subroutine quit
|
||||||
|
|
|
@ -497,9 +497,9 @@ subroutine results_mapping_phase(ID,entry,label)
|
||||||
integer, dimension(:,:), intent(in) :: entry !< phase entry at (co,ce)
|
integer, dimension(:,:), intent(in) :: entry !< phase entry at (co,ce)
|
||||||
character(len=*), dimension(:), intent(in) :: label !< label of each phase section
|
character(len=*), dimension(:), intent(in) :: label !< label of each phase section
|
||||||
|
|
||||||
integer, dimension(size(entry,1),size(entry,2)) :: &
|
integer(pI64), dimension(size(entry,1),size(entry,2)) :: &
|
||||||
entryGlobal
|
entryGlobal
|
||||||
integer, dimension(size(label),0:worldsize-1) :: entryOffset !< offset in entry counting per process
|
integer(pI64), dimension(size(label),0:worldsize-1) :: entryOffset !< offset in entry counting per process
|
||||||
integer, dimension(0:worldsize-1) :: writeSize !< amount of data written per process
|
integer, dimension(0:worldsize-1) :: writeSize !< amount of data written per process
|
||||||
integer(HSIZE_T), dimension(2) :: &
|
integer(HSIZE_T), dimension(2) :: &
|
||||||
myShape, & !< shape of the dataset (this process)
|
myShape, & !< shape of the dataset (this process)
|
||||||
|
@ -507,6 +507,7 @@ subroutine results_mapping_phase(ID,entry,label)
|
||||||
totalShape !< shape of the dataset (all processes)
|
totalShape !< shape of the dataset (all processes)
|
||||||
|
|
||||||
integer(HID_T) :: &
|
integer(HID_T) :: &
|
||||||
|
pI64_t, & !< HDF5 type for pI64 (8 bit integer)
|
||||||
loc_id, & !< identifier of group in file
|
loc_id, & !< identifier of group in file
|
||||||
dtype_id, & !< identifier of compound data type
|
dtype_id, & !< identifier of compound data type
|
||||||
label_id, & !< identifier of label (string) in compound data type
|
label_id, & !< identifier of label (string) in compound data type
|
||||||
|
@ -518,7 +519,8 @@ subroutine results_mapping_phase(ID,entry,label)
|
||||||
dt_id
|
dt_id
|
||||||
|
|
||||||
integer(SIZE_T) :: type_size_string, type_size_int
|
integer(SIZE_T) :: type_size_string, type_size_int
|
||||||
integer :: hdferr, ierr, ce, co
|
integer :: hdferr, ce, co
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
|
|
||||||
writeSize = 0
|
writeSize = 0
|
||||||
|
@ -528,28 +530,28 @@ subroutine results_mapping_phase(ID,entry,label)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
#ifndef PETSC
|
#ifndef PETSC
|
||||||
entryGlobal = entry -1 ! 0-based
|
entryGlobal = int(entry -1,pI64) ! 0-based
|
||||||
#else
|
#else
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! MPI settings and communication
|
! MPI settings and communication
|
||||||
call h5pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr)
|
call h5pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INT,MPI_SUM,MPI_COMM_WORLD,ierr) ! get output at each process
|
call MPI_Allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI) ! get output at each process
|
||||||
if(ierr /= 0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
entryOffset = 0
|
entryOffset = 0_pI64
|
||||||
do co = 1, size(ID,1)
|
do co = 1, size(ID,1)
|
||||||
do ce = 1, size(ID,2)
|
do ce = 1, size(ID,2)
|
||||||
entryOffset(ID(co,ce),worldrank) = entryOffset(ID(co,ce),worldrank) +1
|
entryOffset(ID(co,ce),worldrank) = entryOffset(ID(co,ce),worldrank) +1_pI64
|
||||||
end do
|
end do
|
||||||
end do
|
end do
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,entryOffset,size(entryOffset),MPI_INT,MPI_SUM,MPI_COMM_WORLD,ierr)! get offset at each process
|
call MPI_Allreduce(MPI_IN_PLACE,entryOffset,size(entryOffset),MPI_INTEGER8,MPI_SUM,MPI_COMM_WORLD,err_MPI)! get offset at each process
|
||||||
if(ierr /= 0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
entryOffset(:,worldrank) = sum(entryOffset(:,0:worldrank-1),2)
|
entryOffset(:,worldrank) = sum(entryOffset(:,0:worldrank-1),2)
|
||||||
do co = 1, size(ID,1)
|
do co = 1, size(ID,1)
|
||||||
do ce = 1, size(ID,2)
|
do ce = 1, size(ID,2)
|
||||||
entryGlobal(co,ce) = entry(co,ce) -1 + entryOffset(ID(co,ce),worldrank)
|
entryGlobal(co,ce) = int(entry(co,ce),pI64) -1_pI64 + entryOffset(ID(co,ce),worldrank)
|
||||||
end do
|
end do
|
||||||
end do
|
end do
|
||||||
#endif
|
#endif
|
||||||
|
@ -567,14 +569,15 @@ subroutine results_mapping_phase(ID,entry,label)
|
||||||
call h5tget_size_f(dt_id, type_size_string, hdferr)
|
call h5tget_size_f(dt_id, type_size_string, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call h5tget_size_f(H5T_NATIVE_INTEGER, type_size_int, hdferr)
|
pI64_t = h5kind_to_type(kind(entryGlobal),H5_INTEGER_KIND)
|
||||||
|
call h5tget_size_f(pI64_t, type_size_int, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call h5tcreate_f(H5T_COMPOUND_F, type_size_string + type_size_int, dtype_id, hdferr)
|
call h5tcreate_f(H5T_COMPOUND_F, type_size_string + type_size_int, dtype_id, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
call h5tinsert_f(dtype_id, 'label', 0_SIZE_T, dt_id,hdferr)
|
call h5tinsert_f(dtype_id, 'label', 0_SIZE_T, dt_id,hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
call h5tinsert_f(dtype_id, 'entry', type_size_string, H5T_NATIVE_INTEGER, hdferr)
|
call h5tinsert_f(dtype_id, 'entry', type_size_string, pI64_t, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -586,7 +589,7 @@ subroutine results_mapping_phase(ID,entry,label)
|
||||||
|
|
||||||
call h5tcreate_f(H5T_COMPOUND_F, type_size_int, entry_id, hdferr)
|
call h5tcreate_f(H5T_COMPOUND_F, type_size_int, entry_id, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
call h5tinsert_f(entry_id, 'entry', 0_SIZE_T, H5T_NATIVE_INTEGER, hdferr)
|
call h5tinsert_f(entry_id, 'entry', 0_SIZE_T, pI64_t, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call h5tclose_f(dt_id, hdferr)
|
call h5tclose_f(dt_id, hdferr)
|
||||||
|
@ -650,9 +653,9 @@ subroutine results_mapping_homogenization(ID,entry,label)
|
||||||
integer, dimension(:), intent(in) :: entry !< homogenization entry at (ce)
|
integer, dimension(:), intent(in) :: entry !< homogenization entry at (ce)
|
||||||
character(len=*), dimension(:), intent(in) :: label !< label of each homogenization section
|
character(len=*), dimension(:), intent(in) :: label !< label of each homogenization section
|
||||||
|
|
||||||
integer, dimension(size(entry,1)) :: &
|
integer(pI64), dimension(size(entry,1)) :: &
|
||||||
entryGlobal
|
entryGlobal
|
||||||
integer, dimension(size(label),0:worldsize-1) :: entryOffset !< offset in entry counting per process
|
integer(pI64), dimension(size(label),0:worldsize-1) :: entryOffset !< offset in entry counting per process
|
||||||
integer, dimension(0:worldsize-1) :: writeSize !< amount of data written per process
|
integer, dimension(0:worldsize-1) :: writeSize !< amount of data written per process
|
||||||
integer(HSIZE_T), dimension(1) :: &
|
integer(HSIZE_T), dimension(1) :: &
|
||||||
myShape, & !< shape of the dataset (this process)
|
myShape, & !< shape of the dataset (this process)
|
||||||
|
@ -660,6 +663,7 @@ subroutine results_mapping_homogenization(ID,entry,label)
|
||||||
totalShape !< shape of the dataset (all processes)
|
totalShape !< shape of the dataset (all processes)
|
||||||
|
|
||||||
integer(HID_T) :: &
|
integer(HID_T) :: &
|
||||||
|
pI64_t, & !< HDF5 type for pI64 (8 bit integer)
|
||||||
loc_id, & !< identifier of group in file
|
loc_id, & !< identifier of group in file
|
||||||
dtype_id, & !< identifier of compound data type
|
dtype_id, & !< identifier of compound data type
|
||||||
label_id, & !< identifier of label (string) in compound data type
|
label_id, & !< identifier of label (string) in compound data type
|
||||||
|
@ -671,7 +675,8 @@ subroutine results_mapping_homogenization(ID,entry,label)
|
||||||
dt_id
|
dt_id
|
||||||
|
|
||||||
integer(SIZE_T) :: type_size_string, type_size_int
|
integer(SIZE_T) :: type_size_string, type_size_int
|
||||||
integer :: hdferr, ierr, ce
|
integer :: hdferr, ce
|
||||||
|
integer(MPI_INTEGER_KIND) :: err_MPI
|
||||||
|
|
||||||
|
|
||||||
writeSize = 0
|
writeSize = 0
|
||||||
|
@ -681,25 +686,25 @@ subroutine results_mapping_homogenization(ID,entry,label)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
#ifndef PETSC
|
#ifndef PETSC
|
||||||
entryGlobal = entry -1 ! 0-based
|
entryGlobal = int(entry -1,pI64) ! 0-based
|
||||||
#else
|
#else
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
! MPI settings and communication
|
! MPI settings and communication
|
||||||
call h5pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr)
|
call h5pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INT,MPI_SUM,MPI_COMM_WORLD,ierr) ! get output at each process
|
call MPI_Allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI) ! get output at each process
|
||||||
if(ierr /= 0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
|
|
||||||
entryOffset = 0
|
entryOffset = 0_pI64
|
||||||
do ce = 1, size(ID,1)
|
do ce = 1, size(ID,1)
|
||||||
entryOffset(ID(ce),worldrank) = entryOffset(ID(ce),worldrank) +1
|
entryOffset(ID(ce),worldrank) = entryOffset(ID(ce),worldrank) +1_pI64
|
||||||
end do
|
end do
|
||||||
call MPI_Allreduce(MPI_IN_PLACE,entryOffset,size(entryOffset),MPI_INT,MPI_SUM,MPI_COMM_WORLD,ierr)! get offset at each process
|
call MPI_Allreduce(MPI_IN_PLACE,entryOffset,size(entryOffset),MPI_INTEGER8,MPI_SUM,MPI_COMM_WORLD,err_MPI)! get offset at each process
|
||||||
if(ierr /= 0) error stop 'MPI error'
|
if(err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error'
|
||||||
entryOffset(:,worldrank) = sum(entryOffset(:,0:worldrank-1),2)
|
entryOffset(:,worldrank) = sum(entryOffset(:,0:worldrank-1),2)
|
||||||
do ce = 1, size(ID,1)
|
do ce = 1, size(ID,1)
|
||||||
entryGlobal(ce) = entry(ce) -1 + entryOffset(ID(ce),worldrank)
|
entryGlobal(ce) = int(entry(ce),pI64) -1_pI64 + entryOffset(ID(ce),worldrank)
|
||||||
end do
|
end do
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -716,14 +721,15 @@ subroutine results_mapping_homogenization(ID,entry,label)
|
||||||
call h5tget_size_f(dt_id, type_size_string, hdferr)
|
call h5tget_size_f(dt_id, type_size_string, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call h5tget_size_f(H5T_NATIVE_INTEGER, type_size_int, hdferr)
|
pI64_t = h5kind_to_type(kind(entryGlobal),H5_INTEGER_KIND)
|
||||||
|
call h5tget_size_f(pI64_t, type_size_int, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call h5tcreate_f(H5T_COMPOUND_F, type_size_string + type_size_int, dtype_id, hdferr)
|
call h5tcreate_f(H5T_COMPOUND_F, type_size_string + type_size_int, dtype_id, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
call h5tinsert_f(dtype_id, 'label', 0_SIZE_T, dt_id,hdferr)
|
call h5tinsert_f(dtype_id, 'label', 0_SIZE_T, dt_id,hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
call h5tinsert_f(dtype_id, 'entry', type_size_string, H5T_NATIVE_INTEGER, hdferr)
|
call h5tinsert_f(dtype_id, 'entry', type_size_string, pI64_t, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
!--------------------------------------------------------------------------------------------------
|
!--------------------------------------------------------------------------------------------------
|
||||||
|
@ -735,7 +741,7 @@ subroutine results_mapping_homogenization(ID,entry,label)
|
||||||
|
|
||||||
call h5tcreate_f(H5T_COMPOUND_F, type_size_int, entry_id, hdferr)
|
call h5tcreate_f(H5T_COMPOUND_F, type_size_int, entry_id, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
call h5tinsert_f(entry_id, 'entry', 0_SIZE_T, H5T_NATIVE_INTEGER, hdferr)
|
call h5tinsert_f(entry_id, 'entry', 0_SIZE_T, pI64_t, hdferr)
|
||||||
if(hdferr < 0) error stop 'HDF5 error'
|
if(hdferr < 0) error stop 'HDF5 error'
|
||||||
|
|
||||||
call h5tclose_f(dt_id, hdferr)
|
call h5tclose_f(dt_id, hdferr)
|
||||||
|
|
|
@ -270,7 +270,7 @@ pure elemental subroutine standardize(self)
|
||||||
|
|
||||||
class(rotation), intent(inout) :: self
|
class(rotation), intent(inout) :: self
|
||||||
|
|
||||||
if (self%q(1) < 0.0_pReal) self%q = - self%q
|
if (sign(1.0_pReal,self%q(1)) < 0.0_pReal) self%q = - self%q
|
||||||
|
|
||||||
end subroutine standardize
|
end subroutine standardize
|
||||||
|
|
||||||
|
@ -450,7 +450,7 @@ pure function qu2om(qu) result(om)
|
||||||
om(3,2) = 2.0_pReal*(qu(4)*qu(3)+qu(1)*qu(2))
|
om(3,2) = 2.0_pReal*(qu(4)*qu(3)+qu(1)*qu(2))
|
||||||
om(1,3) = 2.0_pReal*(qu(2)*qu(4)+qu(1)*qu(3))
|
om(1,3) = 2.0_pReal*(qu(2)*qu(4)+qu(1)*qu(3))
|
||||||
|
|
||||||
if (P < 0.0_pReal) om = transpose(om)
|
if (sign(1.0_pReal,P) < 0.0_pReal) om = transpose(om)
|
||||||
|
|
||||||
end function qu2om
|
end function qu2om
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ pure function qu2eu(qu) result(eu)
|
||||||
atan2( 2.0_pReal*chi, q03-q12 ), &
|
atan2( 2.0_pReal*chi, q03-q12 ), &
|
||||||
atan2(( P*qu(1)*qu(3)+qu(2)*qu(4))*chi, (-P*qu(1)*qu(2)+qu(3)*qu(4))*chi )]
|
atan2(( P*qu(1)*qu(3)+qu(2)*qu(4))*chi, (-P*qu(1)*qu(2)+qu(3)*qu(4))*chi )]
|
||||||
endif degenerated
|
endif degenerated
|
||||||
where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI])
|
where(sign(1.0_pReal,eu)<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI])
|
||||||
|
|
||||||
end function qu2eu
|
end function qu2eu
|
||||||
|
|
||||||
|
@ -602,7 +602,7 @@ pure function om2qu(om) result(qu)
|
||||||
qu = [ (om(2,1) - om(1,2)) /s,(om(1,3) + om(3,1)) / s,(om(2,3) + om(3,2)) / s,0.25_pReal * s]
|
qu = [ (om(2,1) - om(1,2)) /s,(om(1,3) + om(3,1)) / s,(om(2,3) + om(3,2)) / s,0.25_pReal * s]
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
if(qu(1)<0._pReal) qu =-1.0_pReal * qu
|
if(sign(1.0_pReal,qu(1))<0.0_pReal) qu =-1.0_pReal * qu
|
||||||
qu = qu*[1.0_pReal,P,P,P]
|
qu = qu*[1.0_pReal,P,P,P]
|
||||||
|
|
||||||
end function om2qu
|
end function om2qu
|
||||||
|
@ -628,7 +628,7 @@ pure function om2eu(om) result(eu)
|
||||||
eu = [atan2(om(1,2),om(1,1)), 0.5_pReal*PI*(1.0_pReal-om(3,3)),0.0_pReal ]
|
eu = [atan2(om(1,2),om(1,1)), 0.5_pReal*PI*(1.0_pReal-om(3,3)),0.0_pReal ]
|
||||||
end if
|
end if
|
||||||
where(abs(eu) < 1.e-8_pReal) eu = 0.0_pReal
|
where(abs(eu) < 1.e-8_pReal) eu = 0.0_pReal
|
||||||
where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI])
|
where(sign(1.0_pReal,eu)<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI])
|
||||||
|
|
||||||
end function om2eu
|
end function om2eu
|
||||||
|
|
||||||
|
@ -735,7 +735,7 @@ pure function eu2qu(eu) result(qu)
|
||||||
-P*sPhi*cos(ee(1)-ee(3)), &
|
-P*sPhi*cos(ee(1)-ee(3)), &
|
||||||
-P*sPhi*sin(ee(1)-ee(3)), &
|
-P*sPhi*sin(ee(1)-ee(3)), &
|
||||||
-P*cPhi*sin(ee(1)+ee(3))]
|
-P*cPhi*sin(ee(1)+ee(3))]
|
||||||
if(qu(1) < 0.0_pReal) qu = qu * (-1.0_pReal)
|
if(sign(1.0_pReal,qu(1)) < 0.0_pReal) qu = qu * (-1.0_pReal)
|
||||||
|
|
||||||
end function eu2qu
|
end function eu2qu
|
||||||
|
|
||||||
|
@ -792,7 +792,7 @@ pure function eu2ax(eu) result(ax)
|
||||||
else
|
else
|
||||||
ax(1:3) = -P/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front
|
ax(1:3) = -P/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front
|
||||||
ax(4) = alpha
|
ax(4) = alpha
|
||||||
if (alpha < 0.0_pReal) ax = -ax ! ensure alpha is positive
|
if (sign(1.0_pReal,alpha) < 0.0_pReal) ax = -ax ! ensure alpha is positive
|
||||||
end if
|
end if
|
||||||
|
|
||||||
end function eu2ax
|
end function eu2ax
|
||||||
|
|
Loading…
Reference in New Issue