Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae695de95a | ||
|
|
5436debf31 | ||
|
|
2c875db251 |
+2
-2
@@ -12,7 +12,7 @@ coverage:
|
||||
threshold: 0%
|
||||
base: auto
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
if_ci_failed: error
|
||||
informational: true
|
||||
only_pulls: true
|
||||
@@ -22,7 +22,7 @@ coverage:
|
||||
threshold: 1% # allows variations around the target
|
||||
base: auto
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
if_ci_failed: error
|
||||
only_pulls: true
|
||||
|
||||
|
||||
+70
-529
@@ -9,550 +9,91 @@
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# DESCRIPTION:
|
||||
###############################################################################
|
||||
# General GitLab pipelines configurations for supercomputers and Linux clusters
|
||||
# at Lawrence Livermore National Laboratory (LLNL).
|
||||
# This entire pipeline is LLNL-specific
|
||||
#
|
||||
# Important note: This file is a template provided by llnl/radiuss-shared-ci.
|
||||
# Remains to set variable values, change the reference to the radiuss-shared-ci
|
||||
# repo, opt-in and out optional features. The project can then extend it with
|
||||
# additional stages.
|
||||
#
|
||||
# In addition, each project should copy over and complete:
|
||||
# - .gitlab/custom-jobs-and-variables.yml
|
||||
# - .gitlab/subscribed-pipelines.yml
|
||||
#
|
||||
# The jobs should be specified in a file local to the project,
|
||||
# - .gitlab/jobs/${CI_MACHINE}.yml
|
||||
# or generated (see LLNL/Umpire for an example).
|
||||
###############################################################################
|
||||
# MAP OF GITLAB CI
|
||||
#######################
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# File dependencies: direct, through jobs, through variables
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# .gitlab-ci.yml
|
||||
# ├── .build-and-test [job]
|
||||
# │ ├── .gitlab/custom-jobs-and-variables.yml
|
||||
# │ │ ├── .custom_job [job]
|
||||
# │ │ ├── .reproducer_vars [job]
|
||||
# │ │ ├── .report_job_success [job]
|
||||
# │ │ │ └── .gitlab/scripts/report_build_and_test [script]
|
||||
# │ │ │ ├── .gitlab/scripts/safe_create_rundir [script]
|
||||
# │ │ │ └── .gitlab/scripts/git_try_to_push [script]
|
||||
# │ │ ├── .report_job_failure [job]
|
||||
# │ │ │ └── .gitlab/scripts/report_build_and_test [script]
|
||||
# │ │ │ ├── .gitlab/scripts/safe_create_rundir [script]
|
||||
# │ │ │ └── .gitlab/scripts/git_try_to_push [script]
|
||||
# │ │ └── JOB_CMD [var]
|
||||
# │ │ └── tests/gitlab/build_and_test [script]
|
||||
# │ │ └── tests/gitlab/get_mfem_uberenv [script]
|
||||
# │ ├── <radiuss-shared-ci>/pipelines/matrix.yml [conditional]
|
||||
# │ │ ├── .on_matrix [job]
|
||||
# │ │ ├── .matrix_reproducer_init [job]
|
||||
# │ │ ├── .matrix_reproducer_vars [job]
|
||||
# │ │ ├── .matrix_reproducer_job [job]
|
||||
# │ │ ├── .matrix_job_command [job]
|
||||
# │ │ └── .job_on_matrix [job]
|
||||
# │ ├── <radiuss-shared-ci>/pipelines/dane.yml [conditional]
|
||||
# │ │ ├── .on_dane [job]
|
||||
# │ │ ├── .dane_reproducer_init [job]
|
||||
# │ │ ├── .dane_reproducer_vars [job]
|
||||
# │ │ ├── .dane_reproducer_job [job]
|
||||
# │ │ ├── .dane_job_command [job]
|
||||
# │ │ ├── .job_on_dane [job]
|
||||
# │ │ ├── allocate_resources [job]
|
||||
# │ │ └── release_resources [job]
|
||||
# │ ├── <radiuss-shared-ci>/pipelines/tioga.yml [conditional]
|
||||
# │ │ ├── .on_tioga [job]
|
||||
# │ │ ├── .tioga_reproducer_init [job]
|
||||
# │ │ ├── .tioga_reproducer_vars [job]
|
||||
# │ │ ├── .tioga_reproducer_job [job]
|
||||
# │ │ ├── .tioga_job_command [job]
|
||||
# │ │ ├── .job_on_tioga [job]
|
||||
# │ │ ├── allocate_resources [job]
|
||||
# │ │ └── release_resources [job]
|
||||
# │ ├── <artifact>/matrix-jobs.yml [conditional, from 'generate-job-lists']
|
||||
# │ │ ├── .gitlab/jobs/matrix.yml
|
||||
# │ │ │ ├── .matrix_reproducer_vars [job]
|
||||
# │ │ │ ├── setup [job]
|
||||
# │ │ │ │ └── ./tests/gitlab/build_and_test_setup [script]
|
||||
# │ │ │ ├── opt_mpi_cuda_gcc [job]
|
||||
# │ │ │ └── opt_mpi_cuda_hypre_cuda_gcc [job]
|
||||
# │ │ └── .gitlab/jobs/matrix-reports.yml [used conditionally]
|
||||
# │ │ ├── report_job_success
|
||||
# │ │ └── report_job_failure
|
||||
# │ ├── <artifact>/dane-jobs.yml [conditional, from 'generate-job-lists']
|
||||
# │ │ ├── .gitlab/jobs/dane.yml
|
||||
# │ │ │ ├── .dane_reproducer_vars [job]
|
||||
# │ │ │ ├── setup [job]
|
||||
# │ │ │ │ └── ./tests/gitlab/build_and_test_setup [script]
|
||||
# │ │ │ ├── debug_ser_gcc_10 [job]
|
||||
# │ │ │ ├── debug_par_gcc_10 [job]
|
||||
# │ │ │ ├── opt_ser_gcc_10 [job]
|
||||
# │ │ │ ├── opt_par_gcc_10 [job]
|
||||
# │ │ │ ├── opt_par_gcc_10_sundials [job]
|
||||
# │ │ │ ├── opt_par_gcc_10_petsc [job]
|
||||
# │ │ │ └── opt_par_gcc_10_pumi [job]
|
||||
# │ │ └── .gitlab/jobs/dane-reports.yml [used conditionally]
|
||||
# │ │ ├── report_job_success
|
||||
# │ │ └── report_job_failure
|
||||
# │ └── <artifact>/tioga-jobs.yml [conditional, from 'generate-job-lists']
|
||||
# │ ├── .gitlab/jobs/tioga.yml
|
||||
# │ │ ├── .tioga_reproducer_vars [job]
|
||||
# │ │ ├── setup [job]
|
||||
# │ │ │ └── ./tests/gitlab/build_and_test_setup [script]
|
||||
# │ │ └── cce_16_0_1 [job]
|
||||
# │ └── .gitlab/jobs/tioga-reports.yml [used conditionally]
|
||||
# │ ├── report_job_success
|
||||
# │ └── report_job_failure
|
||||
# └── .gitlab/subscribed-pipelines.yml
|
||||
# ├── .machine-check [job]
|
||||
# ├── generate-job-lists [job]
|
||||
# ├── dane-up-check [job]
|
||||
# ├── dane-build-and-test [job]
|
||||
# ├── dane-baseline [job]
|
||||
# │ └── .gitlab/dane-baseline.yml
|
||||
# │ ├── .on_dane [job]
|
||||
# │ ├── baselinecheck_mfem_intel_dane [job]
|
||||
# │ │ └── .gitlab/scripts/baseline [script]
|
||||
# │ ├── cleanup [job]
|
||||
# │ ├── report_baseline [job]
|
||||
# │ │ ├── .gitlab/scripts/safe_create_rundir [script]
|
||||
# │ │ └── .gitlab/scripts/git_try_to_push [script]
|
||||
# │ ├── baselinepublish_mfem_dane [job]
|
||||
# │ │ └── .gitlab/scripts/rebaseline [script]
|
||||
# │ ├── .gitlab/custom-jobs-and-variables.yml
|
||||
# │ │ └── <same as above: see .gitlab-ci.yml/.build-and-test>
|
||||
# │ └── .gitlab/configs/setup-baseline.yml
|
||||
# │ └── setup_baseline [job]
|
||||
# ├── tioga-up-check [job]
|
||||
# ├── tioga-build-and-test [job]
|
||||
# ├── matrix-up-check [job]
|
||||
# └── matrix-build-and-test [job]
|
||||
#
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# File tree hierarchy with file contents highlights
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# In addition to the files in the MFEM repo, the Gitlab CI uses files from the
|
||||
# radiuss/radiuss-shared-ci project, see below, after the <mfem-root> tree.
|
||||
#
|
||||
# <mfem root>
|
||||
# ├── .gitlab-ci.yml [this file]
|
||||
# │ ├── <jobs>
|
||||
# │ │ └── .build-and-test
|
||||
# │ ├── <included files>
|
||||
# │ │ ├── .gitlab/subscribed-pipelines.yml
|
||||
# │ │ ├── .gitlab/custom-jobs-and-variables.yml [by ".build-and-test"]
|
||||
# │ │ ├── <artifact> [by ".build-and-test"]
|
||||
# │ │ │ ├── artifact: '${CI_MACHINE}-jobs.yml'
|
||||
# │ │ │ └── job: 'generate-job-lists'
|
||||
# │ │ └── <external> [by ".build-and-test"]
|
||||
# │ │ ├── project: 'radiuss/radiuss-shared-ci'
|
||||
# │ │ ├── ref: 'v2025.09.1'
|
||||
# │ │ └── file: 'pipelines/${CI_MACHINE}.yml'
|
||||
# │ └── <defined variables>
|
||||
# │ ├── CUSTOM_CI_BUILDS_DIR
|
||||
# │ ├── USER_CI_TOP_DIR
|
||||
# │ ├── SHARED_REPOS_DIR
|
||||
# │ ├── AUTOTEST_ROOT
|
||||
# │ ├── MFEM_DATA_DIR
|
||||
# │ ├── AUTOTEST
|
||||
# │ ├── AUTOTEST_COMMIT
|
||||
# │ ├── REBASELINE
|
||||
# │ ├── GITHUB_PROJECT_NAME
|
||||
# │ └── GITHUB_PROJECT_ORG
|
||||
# ├── .gitlab
|
||||
# │ ├── configs
|
||||
# │ │ └── setup-baseline.yml
|
||||
# │ │ ├── <jobs>
|
||||
# │ │ │ └── setup_baseline
|
||||
# │ │ └── <used variables>
|
||||
# │ │ ├── MACHINE_NAME
|
||||
# │ │ ├── REBASELINE
|
||||
# │ │ ├── AUTOTEST
|
||||
# │ │ ├── AUTOTEST_COMMIT
|
||||
# │ │ ├── BUILD_ROOT
|
||||
# │ │ ├── TPLS_REPO
|
||||
# │ │ ├── TESTS_REPO
|
||||
# │ │ ├── AUTOTEST_ROOT
|
||||
# │ │ └── AUTOTEST_REPO
|
||||
# │ ├── jobs
|
||||
# │ │ ├── matrix-reports.yml
|
||||
# │ │ │ ├── <jobs>
|
||||
# │ │ │ │ ├── report_job_success
|
||||
# │ │ │ │ └── report_job_failure
|
||||
# │ │ │ └── <used jobs>
|
||||
# │ │ │ ├── .on_matrix
|
||||
# │ │ │ ├── .report_job_success
|
||||
# │ │ │ └── .report_job_failure
|
||||
# │ │ ├── matrix.yml
|
||||
# │ │ │ ├── <jobs>
|
||||
# │ │ │ │ ├── .matrix_reproducer_vars
|
||||
# │ │ │ │ ├── setup
|
||||
# │ │ │ │ ├── opt_mpi_cuda_gcc
|
||||
# │ │ │ │ └── opt_mpi_cuda_hypre_cuda_gcc
|
||||
# │ │ │ ├── <used jobs>
|
||||
# │ │ │ │ ├── .reproducer_vars
|
||||
# │ │ │ │ ├── .on_matrix
|
||||
# │ │ │ │ └── .job_on_matrix
|
||||
# │ │ │ ├── <included and used files>
|
||||
# │ │ │ │ └── tests/gitlab/build_and_test_setup [by "setup"]
|
||||
# │ │ │ └── <defined variables>
|
||||
# │ │ │ └── SPEC
|
||||
# │ │ ├── dane-reports.yml
|
||||
# │ │ │ ├── <jobs>
|
||||
# │ │ │ │ ├── report_job_success
|
||||
# │ │ │ │ └── report_job_failure
|
||||
# │ │ │ └── <used jobs>
|
||||
# │ │ │ ├── .on_dane
|
||||
# │ │ │ ├── .report_job_success
|
||||
# │ │ │ └── .report_job_failure
|
||||
# │ │ ├── dane.yml
|
||||
# │ │ │ ├── <jobs>
|
||||
# │ │ │ │ ├── .dane_reproducer_vars
|
||||
# │ │ │ │ ├── setup
|
||||
# │ │ │ │ ├── debug_ser_gcc_10
|
||||
# │ │ │ │ ├── debug_par_gcc_10
|
||||
# │ │ │ │ ├── opt_ser_gcc_10
|
||||
# │ │ │ │ ├── opt_par_gcc_10
|
||||
# │ │ │ │ ├── opt_par_gcc_10_sundials
|
||||
# │ │ │ │ ├── opt_par_gcc_10_petsc
|
||||
# │ │ │ │ └── opt_par_gcc_10_pumi
|
||||
# │ │ │ ├── <used jobs>
|
||||
# │ │ │ │ ├── .reproducer_vars
|
||||
# │ │ │ │ ├── .on_dane
|
||||
# │ │ │ │ └── .job_on_dane
|
||||
# │ │ │ ├── <included and used files>
|
||||
# │ │ │ │ └── tests/gitlab/build_and_test_setup [by "setup"]
|
||||
# │ │ │ └── <defined variables>
|
||||
# │ │ │ ├── SPEC
|
||||
# │ │ │ └── THREADS
|
||||
# │ │ ├── tioga-reports.yml
|
||||
# │ │ │ ├── <jobs>
|
||||
# │ │ │ │ ├── report_job_success
|
||||
# │ │ │ │ └── report_job_failure
|
||||
# │ │ │ └── <used jobs>
|
||||
# │ │ │ ├── .on_tioga
|
||||
# │ │ │ ├── .report_job_success
|
||||
# │ │ │ └── .report_job_failure
|
||||
# │ │ └── tioga.yml
|
||||
# │ │ ├── <jobs>
|
||||
# │ │ │ ├── .tioga_reproducer_vars
|
||||
# │ │ │ ├── setup
|
||||
# │ │ │ └── opt_mpi_rocm_hypre_rocm
|
||||
# │ │ ├── <used jobs>
|
||||
# │ │ │ ├── .reproducer_vars
|
||||
# │ │ │ ├── .on_tioga
|
||||
# │ │ │ └── .job_on_tioga
|
||||
# │ │ ├── <included and used files>
|
||||
# │ │ │ └── tests/gitlab/build_and_test_setup [by "setup"]
|
||||
# │ │ └── <defined variables>
|
||||
# │ │ ├── SPEC
|
||||
# │ │ └── THREADS
|
||||
# │ ├── scripts
|
||||
# │ │ ├── baseline
|
||||
# │ │ │ └── <used variables>
|
||||
# │ │ │ ├── BASELINE_TEST
|
||||
# │ │ │ ├── SYS_TYPE
|
||||
# │ │ │ ├── MACHINE_NAME
|
||||
# │ │ │ ├── CI_PROJECT_DIR
|
||||
# │ │ │ ├── ARTIFACTS_DIR
|
||||
# │ │ │ ├── BUILD_ROOT
|
||||
# │ │ │ └── TPLS_DIR
|
||||
# │ │ ├── git_try_to_push
|
||||
# │ │ ├── rebaseline
|
||||
# │ │ │ └── <used variables>
|
||||
# │ │ │ ├── CI_PROJECT_DIR
|
||||
# │ │ │ ├── ARTIFACTS_DIR
|
||||
# │ │ │ ├── SYS_TYPE
|
||||
# │ │ │ ├── BUILD_ROOT
|
||||
# │ │ │ ├── MACHINE_NAME
|
||||
# │ │ │ └── CI_PIPELINE_ID
|
||||
# │ │ ├── report_build_and_test
|
||||
# │ │ │ ├── <used files>
|
||||
# │ │ │ │ ├── .gitlab/scripts/safe_create_rundir
|
||||
# │ │ │ │ └── .gitlab/scripts/git_try_to_push
|
||||
# │ │ │ └── <used variables>
|
||||
# │ │ │ ├── AUTOTEST_ROOT
|
||||
# │ │ │ ├── CI_COMMIT_REF_SLUG
|
||||
# │ │ │ ├── CI_PROJECT_DIR
|
||||
# │ │ │ ├── CI_PIPELINE_URL
|
||||
# │ │ │ ├── AUTOTEST_COMMIT
|
||||
# │ │ │ └── CI_MACHINE
|
||||
# │ │ └── safe_create_rundir
|
||||
# │ ├── custom-jobs-and-variables.yml
|
||||
# │ │ ├── <jobs>
|
||||
# │ │ │ ├── .custom_job
|
||||
# │ │ │ ├── .reproducer_vars
|
||||
# │ │ │ ├── .report_job_success
|
||||
# │ │ │ └── .report_job_failure
|
||||
# │ │ ├── <used files>
|
||||
# │ │ │ ├── tests/gitlab/build_and_test [in JOB_CMD]
|
||||
# │ │ │ └── .gitlab/scripts/report_build_and_test [by .report_job_*]
|
||||
# │ │ ├── <defined variables>
|
||||
# │ │ │ ├── JOB_CMD
|
||||
# │ │ │ ├── BUILD_ROOT
|
||||
# │ │ │ ├── ALLOC_NAME
|
||||
# │ │ │ ├── TPLS_REPO
|
||||
# │ │ │ ├── TESTS_REPO
|
||||
# │ │ │ ├── AUTOTEST_REPO
|
||||
# │ │ │ ├── MFEM_DATA_REPO
|
||||
# │ │ │ ├── ARTIFACTS_DIR: artifacts
|
||||
# │ │ │ ├── SLURM_OVERLAP: 1
|
||||
# │ │ │ ├── DANE_SHARED_ALLOC
|
||||
# │ │ │ ├── DANE_JOB_ALLOC
|
||||
# │ │ │ ├── TIOGA_SHARED_ALLOC
|
||||
# │ │ │ ├── TIOGA_JOB_ALLOC
|
||||
# │ │ │ └── MATRIX_JOB_ALLOC
|
||||
# │ │ └── <used variables>
|
||||
# │ │ ├── SPEC
|
||||
# │ │ ├── BUILD_ROOT
|
||||
# │ │ └── ...
|
||||
# │ ├── dane-baseline.yml
|
||||
# │ │ ├── <jobs>
|
||||
# │ │ │ ├── .on_dane
|
||||
# │ │ │ ├── baselinecheck_mfem_intel_dane
|
||||
# │ │ │ ├── cleanup
|
||||
# │ │ │ ├── report_baseline
|
||||
# │ │ │ └── baselinepublish_mfem_dane
|
||||
# │ │ ├── <included and used files>
|
||||
# │ │ │ ├── .gitlab/custom-jobs-and-variables.yml
|
||||
# │ │ │ ├── .gitlab/configs/setup-baseline.yml
|
||||
# │ │ │ ├── .gitlab/scripts/rebaseline
|
||||
# │ │ │ ├── .gitlab/scripts/baseline
|
||||
# │ │ │ └── .gitlab/scripts/git_try_to_push
|
||||
# │ │ ├── <defined variables>
|
||||
# │ │ │ ├── BASELINE_TEST: baseline
|
||||
# │ │ │ ├── MACHINE_NAME: dane
|
||||
# │ │ │ ├── TPLS_DIR
|
||||
# │ │ │ └── export MFEM_TEST_NP
|
||||
# │ │ └── <used variables>
|
||||
# │ │ ├── ON_DANE
|
||||
# │ │ ├── AUTOTEST [defined by .gitlab-ci.yml]
|
||||
# │ │ ├── BUILD_ROOT [defined by custom-jobs-and-variables.yml]
|
||||
# │ │ ├── TPLS_DIR [defined by this file]
|
||||
# │ │ ├── ARTIFACTS_DIR [defined by custom-jobs-and-variables.yml]
|
||||
# │ │ ├── MACHINE_NAME [defined by this file]
|
||||
# │ │ ├── AUTOTEST_COMMIT [defined by .gitlab-ci.yml]
|
||||
# │ │ ├── AUTOTEST_ROOT [defined by .gitlab-ci.yml]
|
||||
# │ │ ├── BASELINE_TEST [defined by this file]
|
||||
# │ │ └── REBASELINE [defined by .gitlab-ci.yml]
|
||||
# │ └── subscribed-pipelines.yml
|
||||
# │ ├── <jobs>
|
||||
# │ │ ├── .machine-check
|
||||
# │ │ ├── generate-job-lists
|
||||
# │ │ ├── dane-up-check
|
||||
# │ │ ├── dane-build-and-test
|
||||
# │ │ ├── dane-baseline
|
||||
# │ │ ├── tioga-up-check
|
||||
# │ │ ├── tioga-build-and-test
|
||||
# │ │ ├── matrix-up-check
|
||||
# │ │ └── matrix-build-and-test
|
||||
# │ ├── <used jobs>
|
||||
# │ │ └── .build-and-test [from ".gitlab-ci.yml"]
|
||||
# │ ├── <included files>
|
||||
# │ │ └── .gitlab/dane-baseline.yml [by "dane-baseline"]
|
||||
# │ └── <used variables>
|
||||
# │ ├── GITHUB_PROJECT_ORG
|
||||
# │ ├── GITHUB_PROJECT_NAME
|
||||
# │ ├── AUTOTEST
|
||||
# │ ├── AUTOTEST_COMMIT
|
||||
# │ └── REBASELINE
|
||||
# └── tests
|
||||
# ├── gitlab
|
||||
# │ ├── build_and_test
|
||||
# │ │ ├── <builds and tests a given MFEM spec with uberenv>
|
||||
# │ │ ├── <used files>
|
||||
# │ │ │ ├── tests/uberenv/uberenv.py [deps mode, cloned]
|
||||
# │ │ │ └── tests/gitlab/get_mfem_uberenv [deps mode]
|
||||
# │ │ └── <used variables>
|
||||
# │ │ ├── SYS_TYPE
|
||||
# │ │ ├── THREADS [num. parallel jobs to build MFEM]
|
||||
# │ │ ├── MODULE_LIST [modules to load]
|
||||
# │ │ ├── CI_JOB_ID
|
||||
# │ │ ├── USE_DEV_SHM
|
||||
# │ │ ├── SPACK_DEBUG
|
||||
# │ │ ├── DEBUG_MODE
|
||||
# │ │ ├── REGISTRY_TOKEN
|
||||
# │ │ ├── CI_REGISTRY_USER (defined by Gitlab)
|
||||
# │ │ ├── USER
|
||||
# │ │ ├── CI_REGISTRY_IMAGE (defined by Gitlab)
|
||||
# │ │ └── CI_JOB_TOKEN (defined by Gitlab)
|
||||
# │ ├── build_and_test_setup
|
||||
# │ │ ├── <updates MFEM_DATA_REPO and AUTOTEST_REPO using locks>
|
||||
# │ │ └── <used variables>
|
||||
# │ │ ├── MFEM_DATA_REPO
|
||||
# │ │ ├── SHARED_REPOS_DIR
|
||||
# │ │ ├── AUTOTEST_REPO
|
||||
# │ │ └── AUTOTEST_ROOT
|
||||
# │ └── get_mfem_uberenv
|
||||
# │ ├── <github.com/mfem/mfem-uberenv.git -> tests/uberenv>
|
||||
# │ └── <defines the uberenv hash to use>
|
||||
# └── uberenv [cloned by tests/gitlab/get_mfem_uberenv]
|
||||
# └── uberenv.py
|
||||
#
|
||||
# <root of radiuss/radiuss-shared-ci, ref: 'v2025.09.1'>
|
||||
# └── pipelines
|
||||
# ├── matrix.yml
|
||||
# │ ├── <jobs>
|
||||
# │ │ ├── .on_matrix
|
||||
# │ │ ├── .matrix_reproducer_init
|
||||
# │ │ ├── .matrix_reproducer_vars
|
||||
# │ │ ├── .matrix_reproducer_job
|
||||
# │ │ ├── .matrix_job_command
|
||||
# │ │ └── .job_on_matrix
|
||||
# │ ├── <used jobs>
|
||||
# │ │ └── .custom_job [from .gitlab/custom-jobs-and-variables.yml]
|
||||
# │ └── <used variables>
|
||||
# │ ├── ON_MATRIX
|
||||
# │ ├── ADVANCED_JOB
|
||||
# │ ├── ALL_TARGETS
|
||||
# │ ├── SYS_TYPE
|
||||
# │ ├── LLNL_SERVICE_USER
|
||||
# │ ├── USER
|
||||
# │ ├── GITHUB_PROJECT_NAME
|
||||
# │ ├── GITHUB_PROJECT_ORG
|
||||
# │ ├── MATRIX_JOB_ALLOC
|
||||
# │ └── JOB_CMD
|
||||
# ├── dane.yml
|
||||
# │ ├── <jobs>
|
||||
# │ │ ├── .on_dane
|
||||
# │ │ ├── .dane_reproducer_init
|
||||
# │ │ ├── .dane_reproducer_vars
|
||||
# │ │ ├── .dane_reproducer_job
|
||||
# │ │ ├── .dane_job_command
|
||||
# │ │ ├── .job_on_dane
|
||||
# │ │ ├── allocate_resources
|
||||
# │ │ └── release_resources
|
||||
# │ ├── <used jobs>
|
||||
# │ │ └── .custom_job [from .gitlab/custom-jobs-and-variables.yml]
|
||||
# │ ├── <defined variables>
|
||||
# │ │ └── export JOBID
|
||||
# │ └── <used variables>
|
||||
# │ ├── ON_DANE
|
||||
# │ ├── ADVANCED_JOB
|
||||
# │ ├── ALL_TARGETS
|
||||
# │ ├── SYS_TYPE
|
||||
# │ ├── LLNL_SERVICE_USER
|
||||
# │ ├── USER
|
||||
# │ ├── GITHUB_PROJECT_NAME
|
||||
# │ ├── GITHUB_PROJECT_ORG
|
||||
# │ ├── DANE_JOB_ALLOC
|
||||
# │ ├── JOB_CMD
|
||||
# │ ├── JOBID
|
||||
# │ ├── ALLOC_NAME
|
||||
# │ └── DANE_SHARED_ALLOC
|
||||
# └── tioga.yml
|
||||
# ├── <jobs>
|
||||
# │ ├── .on_tioga
|
||||
# │ ├── .tioga_reproducer_init
|
||||
# │ ├── .tioga_reproducer_vars
|
||||
# │ ├── .tioga_reproducer_job
|
||||
# │ ├── .tioga_job_command
|
||||
# │ ├── .job_on_tioga
|
||||
# │ ├── allocate_resources
|
||||
# │ └── release_resources
|
||||
# ├── <used jobs>
|
||||
# │ └── .custom_job [from .gitlab/custom-jobs-and-variables.yml]
|
||||
# ├── <defined variables>
|
||||
# │ └── PROXY
|
||||
# └── <used variables>
|
||||
# ├── ON_TIOGA
|
||||
# ├── ADVANCED_JOB
|
||||
# ├── ALL_TARGETS
|
||||
# ├── SYS_TYPE
|
||||
# ├── LLNL_SERVICE_USER
|
||||
# ├── USER
|
||||
# ├── GITHUB_PROJECT_NAME
|
||||
# ├── GITHUB_PROJECT_ORG
|
||||
# ├── TIOGA_JOB_ALLOC
|
||||
# ├── JOB_CMD
|
||||
# ├── PROXY
|
||||
# ├── ALLOC_NAME
|
||||
# └── TIOGA_SHARED_ALLOC
|
||||
# at Lawrence Livermore National Laboratory (LLNL). This entire pipeline is
|
||||
# LLNL-specific!
|
||||
|
||||
include:
|
||||
- project: 'lc-templates/id_tokens'
|
||||
file: 'id_tokens.yml'
|
||||
|
||||
# The pipeline is divided into stages. Usually, jobs in a given stage wait for
|
||||
# the preceding stages to complete before to start. However, we sometimes use
|
||||
# the "needs" keyword and express the DAG of jobs for more efficiency.
|
||||
# - We use setup and setup_baseline phases to download content outside of mfem
|
||||
# directory.
|
||||
# - Allocate/Release is where Dane resource are allocated/released once for all.
|
||||
# - Build and Test is where we build and MFEM for multiple toolchains.
|
||||
# - Baseline_checks gathers baseline-type test suites execution
|
||||
# - Baseline_publish, only available on master, allows to update baseline
|
||||
# results
|
||||
stages:
|
||||
- sub-pipelines
|
||||
|
||||
###############################################################################
|
||||
# We define the following GitLab pipeline variables:
|
||||
variables:
|
||||
##### LC GITLAB CONFIGURATION
|
||||
CUSTOM_CI_BUILDS_DIR: "/usr/workspace/mfem/gitlab-runner"
|
||||
|
||||
##### PROJECT VARIABLES
|
||||
USER_CI_TOP_DIR: "${CUSTOM_CI_BUILDS_DIR}/${GITLAB_USER_LOGIN}"
|
||||
SHARED_REPOS_DIR: "${USER_CI_TOP_DIR}/repos"
|
||||
AUTOTEST_ROOT: "${SHARED_REPOS_DIR}"
|
||||
# MFEM_DATA_DIR is setup in '.gitlab/configs/setup-build-and-test.yml' and
|
||||
# used in '.gitlab/configs/<machine>-config.yml':
|
||||
MFEM_DATA_DIR: "${SHARED_REPOS_DIR}/mfem-data"
|
||||
# AUTOTEST: enable (ON/YES) or disable (any other value) test reporting. See
|
||||
# also AUTOTEST_COMMIT.
|
||||
AUTOTEST: "OFF"
|
||||
# AUTOTEST_COMMIT: used only when AUTOTEST is set to ON/YES.
|
||||
# * If AUTOTEST_COMMIT is set to ON/YES, reporting jobs will commit their
|
||||
# files to the MFEM/autotest repo.
|
||||
# * If AUTOTEST_COMMIT is NOT set to ON/YES, reporting jobs will NOT commit
|
||||
# their files to the MFEM/autotest repo. Instead they will just show the
|
||||
# contents of the report files and remove them.
|
||||
AUTOTEST_COMMIT: "ON"
|
||||
# REBASELINE:
|
||||
|
||||
# Defines the default choice for updating the saved baseline results. By default
|
||||
# the baseline can only be updated from the master branch. This variable offers
|
||||
# the option to manually ask for rebaselining from another branch if necessary.
|
||||
REBASELINE: "OFF"
|
||||
REBASELINE: "NO"
|
||||
AUTOTEST: "NO"
|
||||
# AUTOTEST_COMMIT: used only when AUTOTEST is set to YES.
|
||||
# * If AUTOTEST_COMMIT is NOT set to NO, reporting jobs will commit their
|
||||
# files to the MFEM/autotest repo.
|
||||
# * If AUTOTEST_COMMIT is set to NO, reporting jobs will NOT commit their
|
||||
# files to the MFEM/autotest repo. Instead they will just show the contents
|
||||
# of the report files and remove them.
|
||||
AUTOTEST_COMMIT: "YES"
|
||||
|
||||
##### SHARED_CI CONFIGURATION
|
||||
# Required information about GitHub repository
|
||||
GITHUB_PROJECT_NAME: "mfem"
|
||||
GITHUB_PROJECT_ORG: "MFEM"
|
||||
# Override the pattern describing branches that will skip the "draft PR filter
|
||||
# test". Add protected branches here. See default value in
|
||||
# preliminary-ignore-draft-pr.yml.
|
||||
# ALWAYS_RUN_PATTERN: ""
|
||||
|
||||
###############################################################################
|
||||
##### High level stages
|
||||
# We organize the test-pipelines stage with sub-pipelines. Each sub-pipeline
|
||||
# corresponds to a test batch on a given machine.
|
||||
stages:
|
||||
- prerequisites
|
||||
- test-pipelines
|
||||
|
||||
###############################################################################
|
||||
# Template for jobs triggering a build-and-test sub-pipeline:
|
||||
.build-and-test:
|
||||
stage: test-pipelines
|
||||
# Trigger subpipelines:
|
||||
dane-build-and-test:
|
||||
stage: sub-pipelines
|
||||
variables:
|
||||
# Explicitly pass down values that are not always propagated to child
|
||||
# pipelines, e.g. when a variable is set in the "Settings -> CI" web
|
||||
# interface (project variables).
|
||||
# Note: in some cases, this does not work as expected, e.g. when the
|
||||
# variable is not re-defined in the web interface; in such cases, the child
|
||||
# pipeline gets a definition like '${AUTOTEST}', i.e. it behaves as if
|
||||
# AUTOTEST is undefined, even though there is a default value in
|
||||
# .gitlab-ci.yml.
|
||||
# Explicitly pass down values that we want to be able to set when triggering
|
||||
# pipelines manually or using scheduling
|
||||
AUTOTEST: "${AUTOTEST}"
|
||||
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
|
||||
trigger:
|
||||
include:
|
||||
- local: '.gitlab/custom-jobs-and-variables.yml'
|
||||
- project: 'radiuss/radiuss-shared-ci'
|
||||
ref: 'v2025.09.1'
|
||||
file: 'pipelines/${CI_MACHINE}.yml'
|
||||
- artifact: '${CI_MACHINE}-jobs.yml'
|
||||
job: 'generate-job-lists'
|
||||
include: .gitlab/dane-build-and-test.yml
|
||||
strategy: depend
|
||||
forward:
|
||||
pipeline_variables: true
|
||||
|
||||
###############################################################################
|
||||
include:
|
||||
# Sets ID tokens for every job using `default:`
|
||||
- project: 'lc-templates/id_tokens'
|
||||
file: 'id_tokens.yml'
|
||||
# [Optional] checks preliminary to running the actual CI test
|
||||
#- project: 'radiuss/radiuss-shared-ci'
|
||||
# ref: 'v2025.09.1'
|
||||
# file: 'preliminary-ignore-draft-pr.yml'
|
||||
# pipelines subscribed by the project
|
||||
- local: '.gitlab/subscribed-pipelines.yml'
|
||||
dane-baseline:
|
||||
stage: sub-pipelines
|
||||
variables:
|
||||
# Explicitly pass down values that we want to be able to set when triggering
|
||||
# pipelines manually or using scheduling
|
||||
REBASELINE: "${REBASELINE}"
|
||||
AUTOTEST: "${AUTOTEST}"
|
||||
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
|
||||
trigger:
|
||||
include: .gitlab/dane-baseline.yml
|
||||
strategy: depend
|
||||
|
||||
lassen-build-and-test:
|
||||
stage: sub-pipelines
|
||||
variables:
|
||||
# Explicitly pass down values that we want to be able to set when triggering
|
||||
# pipelines manually or using scheduling
|
||||
AUTOTEST: "${AUTOTEST}"
|
||||
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
|
||||
trigger:
|
||||
include: .gitlab/lassen-build-and-test.yml
|
||||
strategy: depend
|
||||
|
||||
corona-build-and-test:
|
||||
stage: sub-pipelines
|
||||
variables:
|
||||
# Explicitly pass down values that we want to be able to set when triggering
|
||||
# pipelines manually or using scheduling
|
||||
AUTOTEST: "${AUTOTEST}"
|
||||
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
|
||||
trigger:
|
||||
include: .gitlab/corona-build-and-test.yml
|
||||
strategy: depend
|
||||
|
||||
+12
-36
@@ -8,8 +8,6 @@
|
||||
https://mfem.org
|
||||
|
||||
|
||||
FIXME: this file needs to be updated
|
||||
|
||||
This directory contains most of the GitLab CI configuration. MFEM runs both PR
|
||||
and nightly testing on GitLab.
|
||||
|
||||
@@ -17,9 +15,9 @@ and nightly testing on GitLab.
|
||||
|
||||
## Top level
|
||||
|
||||
The root configuration file is `.gitlab-ci.yml` at the root of MFEM repo. This
|
||||
file only defines three stages, a prerequisites one, and two main stages in
|
||||
which we trigger several sub-pipelines.
|
||||
The root configuration file is `.gitlab-ci.yml` at the root of MFEM repo.
|
||||
This file only defines one stage, in which we trigger several
|
||||
sub-pipelines.
|
||||
|
||||
We use sub-pipelines to isolate the test for one combination of `machine`
|
||||
and `test type`.
|
||||
@@ -27,8 +25,8 @@ and `test type`.
|
||||
Machines typically include:
|
||||
|
||||
* Dane: Intel Sapphire Rapids
|
||||
* Matrix: Intel Sapphire Rapids + Nvidia H100 GPU
|
||||
* Tioga: AMD MI250X GPU
|
||||
* Lassen: Power9 + Nvidia GPU
|
||||
* Corona: AMD GPU
|
||||
|
||||
Test types include:
|
||||
|
||||
@@ -41,31 +39,9 @@ altering the scheduling, execution and displaying of the others.
|
||||
|
||||
## Sub-pipelines
|
||||
|
||||
### build-and-test
|
||||
|
||||
The build-and-test sub-pipelines leverage RADIUSS Shared CI to share most of
|
||||
the CI implementation. RADIUSS Shared CI provides a shared CI infrastructure
|
||||
vetted on most LC systems of interest and efficiently leveraging each machine
|
||||
scheduler to increase CI throughput. The maintenance of RADIUSS Shared CI is
|
||||
shared among several RADIUSS projects.
|
||||
|
||||
Jobs for the build-and-test sub-pipelines are defined in the jobs directory.
|
||||
Because build-and-test jobs leverage Uberenv and Spack to build the
|
||||
dependencies automatically, the jobs essentially consists in a `spack spec`
|
||||
defined in the jobs files, and some scheduling parameters defined in the
|
||||
`.gitlab/custom-jobs-and-variables.yml` file.
|
||||
|
||||
Build-and-test jobs all run the `tests/gitlab/build_and_test` script.
|
||||
|
||||
The build-and-test pipelines are controlled by the
|
||||
`.gitlab/subscribed-pipelines.yml` which defines which machines to run on and
|
||||
implements additional features like machine availability check, and job list
|
||||
generation.
|
||||
|
||||
### baseline
|
||||
|
||||
Baseline sub-pipelines are described by files with names reflecting the
|
||||
machine it runs on, e.g. `dane-baseline`.
|
||||
Each file is this directory is the root configuration file for one
|
||||
sub-pipeline. The naming reflects the corresponding couple (`machine`,
|
||||
`test_type`).
|
||||
|
||||
Those files define the *stages* and the *jobs* for the sub-pipeline. They
|
||||
also contain any configuration that cannot be shared. For the most part
|
||||
@@ -87,11 +63,11 @@ usage function. This should be improved.
|
||||
|
||||
# More testing
|
||||
|
||||
## Adding a new target to a build-and-test pipeline
|
||||
## Adding a new target to a build_and_test pipeline
|
||||
|
||||
`build-and-test` pipelines rely on Spack to install dependencies. Spack is
|
||||
`build_and_test` pipelines rely on Spack to install dependencies. Spack is
|
||||
driven by Uberenv which helps freezing Spack configuration: the goal being to
|
||||
point to a specific commit in Spack and isolate its configuration so that it is
|
||||
point to specific commit in Spack and isolate its configuration so that it is
|
||||
not influenced by the user environment. More documentation about this can be
|
||||
found in `tests/gitlab`.
|
||||
|
||||
@@ -106,7 +82,7 @@ spack spec to use. Adding a job on Dane for example resumes to:
|
||||
<job_name>:
|
||||
variables:
|
||||
SPEC: "<spack_spec>"
|
||||
extends: .job_on_dane
|
||||
extends: .build_and_test_on_dane
|
||||
```
|
||||
|
||||
The remaining and non trivial work is to make sure this spec is working. To
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
include:
|
||||
- project: 'lc-templates/id_tokens'
|
||||
file: 'id_tokens.yml'
|
||||
|
||||
# We define the following GitLab pipeline variables:
|
||||
variables:
|
||||
|
||||
# The path to the shared resource between all jobs. For example, external
|
||||
# repositories like 'tests' and 'tpls' are cloned here. Also, 'tpls' is built
|
||||
# once for all targets, so that build happen here. The BUILD_ROOT is unique to
|
||||
# the pipeline, preventing any form of concurrency with other pipelines. This
|
||||
# also means that the BUILD_ROOT directory will never be cleaned.
|
||||
# TODO: add a clean-up mechanism
|
||||
BUILD_ROOT: ${USER_CI_TOP_DIR}/${CI_PROJECT_NAME}-${MACHINE_NAME}-pipeline-${CI_PIPELINE_ID}
|
||||
|
||||
# On LLNL's Dane, there is only one allocation shared among jobs in order to
|
||||
# save time and resource. This allocation has to be uniquely named so that we
|
||||
# are sure to retrieve it.
|
||||
ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID}
|
||||
|
||||
# Git repositories used in the pipeline
|
||||
TPLS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tpls.git
|
||||
TESTS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tests.git
|
||||
AUTOTEST_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/autotest.git
|
||||
MFEM_DATA_REPO: https://github.com/mfem/data.git
|
||||
|
||||
# Directory used to place artifacts.
|
||||
ARTIFACTS_DIR: artifacts
|
||||
SLURM_OVERLAP: 1
|
||||
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# GitLab pipeline configuration for the Corona machine at LLNL
|
||||
variables:
|
||||
MACHINE_NAME: corona
|
||||
|
||||
.on_corona:
|
||||
tags:
|
||||
- shell
|
||||
- corona
|
||||
rules:
|
||||
# Don't run corona jobs if...
|
||||
# Note: This makes corona an "opt-in" machine. To activate builds on corona
|
||||
# for a given GitLab clone of MFEM, go to Setting/CI-CD/variables, and set
|
||||
# "ON_CORONA" to "ON". An LC account on for corona is required to trigger a
|
||||
# pipeline there.
|
||||
- if: '$CI_COMMIT_BRANCH =~ /_cnone/ || $ON_CORONA != "ON"'
|
||||
when: never
|
||||
# Don't run autotest update if...
|
||||
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "YES"'
|
||||
when: never
|
||||
# Report success on success status
|
||||
- if: '$CI_JOB_NAME =~ /report_job_success/ && $AUTOTEST == "YES"'
|
||||
when: on_success
|
||||
# Report failure on failure status
|
||||
- if: '$CI_JOB_NAME =~ /report_job_failure/ && $AUTOTEST == "YES"'
|
||||
when: on_failure
|
||||
# Always release resource
|
||||
- if: '$CI_JOB_NAME =~ /release_resource/'
|
||||
when: always
|
||||
# Always cleanup
|
||||
- if: '$CI_JOB_NAME =~ /cleanup/'
|
||||
when: always
|
||||
# Default is to run if previous stage succeeded
|
||||
- when: on_success
|
||||
|
||||
# Spack helped builds
|
||||
# Generic corona build job, extending build script
|
||||
.build_and_test_on_corona:
|
||||
extends: [.on_corona]
|
||||
stage: build_and_test
|
||||
script:
|
||||
# THREADS is used by 'tests/gitlab/build_and_test', run below
|
||||
- export THREADS=12
|
||||
- echo ${ALLOC_NAME}
|
||||
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
|
||||
- echo ${JOBID}
|
||||
- echo ${MFEM_DATA_DIR}
|
||||
- echo ${SPEC}
|
||||
- srun $( [[ -n "${JOBID}" ]] && echo "--jobid=${JOBID}" ) -t 15 -N 1 tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
|
||||
@@ -0,0 +1,56 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# GitLab pipelines configurations for the Dane machine at LLNL
|
||||
variables:
|
||||
MACHINE_NAME: dane
|
||||
|
||||
.on_dane:
|
||||
tags:
|
||||
- shell
|
||||
- dane
|
||||
rules:
|
||||
# Don't run dane jobs if...
|
||||
- if: '$CI_COMMIT_BRANCH =~ /_qnone/ || $ON_DANE == "OFF"'
|
||||
when: never
|
||||
# Don't run autotest update if...
|
||||
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "YES"'
|
||||
when: never
|
||||
# Report success on success status
|
||||
- if: '$CI_JOB_NAME =~ /report_job_success/ && $AUTOTEST == "YES"'
|
||||
when: on_success
|
||||
# Report failure on failure status
|
||||
- if: '$CI_JOB_NAME =~ /report_job_failure/ && $AUTOTEST == "YES"'
|
||||
when: on_failure
|
||||
# Always release resource
|
||||
- if: '$CI_JOB_NAME =~ /release_resource/'
|
||||
when: always
|
||||
# Always cleanup
|
||||
- if: '$CI_JOB_NAME =~ /cleanup/'
|
||||
when: always
|
||||
# Default is to run if previous stage succeeded
|
||||
- when: on_success
|
||||
|
||||
# Spack helped builds
|
||||
# Generic dane build job, extending build script
|
||||
.build_and_test_on_dane:
|
||||
extends: [.on_dane]
|
||||
stage: build_and_test
|
||||
script:
|
||||
# THREADS is used by 'tests/gitlab/build_and_test', run below
|
||||
# Dane has 224 threads/node and we run 7 separate jobs: 224=7*32
|
||||
- export THREADS=28
|
||||
- echo ${ALLOC_NAME}
|
||||
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
|
||||
- echo ${JOBID}
|
||||
- echo ${MFEM_DATA_DIR}
|
||||
- echo ${SPEC}
|
||||
- srun $( [[ -n "${JOBID}" ]] && echo "--jobid=${JOBID}" ) --reservation=ci -t 60 -N 1 tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
|
||||
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# GitLab pipelines configurations for the Lassen machine at LLNL
|
||||
variables:
|
||||
MACHINE_NAME: lassen
|
||||
|
||||
.on_lassen:
|
||||
tags:
|
||||
- shell
|
||||
- lassen
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH =~ /_lnone/ || $ON_LASSEN == "OFF"' #run except if ...
|
||||
when: never
|
||||
# Don't run autotest update if...
|
||||
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "YES"'
|
||||
when: never
|
||||
# Report success on success status
|
||||
- if: '$CI_JOB_NAME =~ /report_job_success/ && $AUTOTEST == "YES"'
|
||||
when: on_success
|
||||
# Report failure on failure status
|
||||
- if: '$CI_JOB_NAME =~ /report_job_failure/ && $AUTOTEST == "YES"'
|
||||
when: on_failure
|
||||
# Always cleanup
|
||||
- if: '$CI_JOB_NAME =~ /cleanup/'
|
||||
when: always
|
||||
- when: on_success
|
||||
|
||||
# Lassen uses a different job scheduler (spectrum lsf) that does not allow
|
||||
# pre-allocation the same way slurm does. We use the pci queue on lassen
|
||||
# to speed-up the allocation.
|
||||
.build_and_test_on_lassen:
|
||||
extends: [.on_lassen]
|
||||
stage: build_and_test
|
||||
script:
|
||||
- echo ${MFEM_DATA_DIR}
|
||||
- echo ${SPEC}
|
||||
# Next script uses 'THREADS': leaving it empty --> it uses 'make all -j'
|
||||
- lalloc 1 -W 45 -q pci --atsdisable tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
|
||||
needs: [setup]
|
||||
@@ -0,0 +1,77 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Jobs report
|
||||
.report_job_success:
|
||||
script:
|
||||
- echo ${MACHINE_NAME}
|
||||
- echo ${AUTOTEST}
|
||||
- echo ${AUTOTEST_COMMIT}
|
||||
- echo "AUTOTEST_ROOT ${AUTOTEST_ROOT}"
|
||||
- cd ${AUTOTEST_ROOT}
|
||||
- |
|
||||
(
|
||||
date
|
||||
echo "Waiting to acquire lock on '$PWD/autotest.lock' ..."
|
||||
# try to get an exclusive lock on fd 9 (autotest.lock) repeating the try
|
||||
# every 5 seconds; we may want to add a counter for the number of
|
||||
# retries to interrupt a potential infinite loop
|
||||
while ! flock -n 9; do
|
||||
sleep 5
|
||||
done
|
||||
echo "Acquired lock on '$PWD/autotest.lock'"
|
||||
date
|
||||
# Report SUCCESS while holding the file lock on 'autotest.lock'.
|
||||
# The next script uses the following environment variables:
|
||||
# - MACHINE_NAME, AUTOTEST_ROOT, AUTOTEST_COMMIT
|
||||
# - CI_COMMIT_REF_SLUG, CI_PROJECT_DIR, CI_PIPELINE_URL
|
||||
# It also calls the script '.gitlab/scripts/safe_create_rundir'.
|
||||
${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test_success
|
||||
err=$?
|
||||
# sleep for a period to allow NFS to propagate the above changes;
|
||||
# clearly, there is no guarantee that other NFS clients will see the
|
||||
# changes even after the timeout
|
||||
sleep 10
|
||||
exit $err
|
||||
) 9> autotest.lock
|
||||
|
||||
.report_job_failure:
|
||||
script:
|
||||
- echo ${MACHINE_NAME}
|
||||
- echo ${AUTOTEST}
|
||||
- echo ${AUTOTEST_COMMIT}
|
||||
- echo "AUTOTEST_ROOT ${AUTOTEST_ROOT}"
|
||||
- cd ${AUTOTEST_ROOT}
|
||||
- |
|
||||
(
|
||||
date
|
||||
echo "Waiting to acquire lock on '$PWD/autotest.lock' ..."
|
||||
# try to get an exclusive lock on fd 9 (autotest.lock) repeating the try
|
||||
# every 5 seconds; we may want to add a counter for the number of
|
||||
# retries to interrupt a potential infinite loop
|
||||
while ! flock -n 9; do
|
||||
sleep 5
|
||||
done
|
||||
echo "Acquired lock on '$PWD/autotest.lock'"
|
||||
date
|
||||
# Report FAILURE while holding the file lock on 'autotest.lock'.
|
||||
# The next script uses the following environment variables:
|
||||
# - MACHINE_NAME, AUTOTEST_ROOT, AUTOTEST_COMMIT
|
||||
# - CI_COMMIT_REF_SLUG, CI_PROJECT_DIR, CI_PIPELINE_URL
|
||||
# It also calls the script '.gitlab/scripts/safe_create_rundir'.
|
||||
${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test_failure
|
||||
err=$?
|
||||
# sleep for a period to allow NFS to propagate the above changes;
|
||||
# clearly, there is no guarantee that other NFS clients will see the
|
||||
# changes even after the timeout
|
||||
sleep 10
|
||||
exit $err
|
||||
) 9> autotest.lock
|
||||
@@ -0,0 +1,90 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
|
||||
# script then symlinks the repo to the parent directory of the MFEM source
|
||||
# directory. Unit tests that depend on the mfem/data repo will then detect that
|
||||
# this directory is present and be enabled.
|
||||
setup:
|
||||
tags:
|
||||
- shell
|
||||
- dane
|
||||
stage: setup
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
#
|
||||
# Setup MFEM_DATA_DIR=${SHARED_REPOS_DIR}/mfem-data, see '.gitlab-ci.yml'
|
||||
# and '.gitlab/configs/<machine>-config.yml'
|
||||
#
|
||||
- echo "MACHINE_NAME = ${MACHINE_NAME}"
|
||||
- echo "AUTOTEST = ${AUTOTEST}"
|
||||
- echo "AUTOTEST_COMMIT = ${AUTOTEST_COMMIT}"
|
||||
- echo "SHARED_REPOS_DIR ${SHARED_REPOS_DIR}"
|
||||
- mkdir -p ${SHARED_REPOS_DIR} && cd ${SHARED_REPOS_DIR}
|
||||
- command -v flock || echo "Required command 'flock' not found"
|
||||
- |
|
||||
(
|
||||
date
|
||||
echo "Waiting to acquire lock on '$PWD/mfem-data.lock' ..."
|
||||
# try to get an exclusive lock on fd 9 (mfem-data.lock) repeating the
|
||||
# try every 5 seconds; we may want to add a counter for the number of
|
||||
# retries to interrupt a potential infinite loop
|
||||
while ! flock -n 9; do
|
||||
sleep 5
|
||||
done
|
||||
echo "Acquired lock on '$PWD/mfem-data.lock'"
|
||||
date
|
||||
# clone/update the mfem/data repo while holding the file lock on
|
||||
# 'mfem-data.lock'
|
||||
err=0
|
||||
if [[ ! -d "mfem-data" ]]; then
|
||||
git clone ${MFEM_DATA_REPO} "mfem-data"
|
||||
else
|
||||
cd "mfem-data" && git pull && cd ..
|
||||
fi || err=1
|
||||
# sleep for a period to allow NFS to propagate the above changes;
|
||||
# clearly, there is no guarantee that other NFS clients will see the
|
||||
# changes even after the timeout
|
||||
sleep 10
|
||||
exit $err
|
||||
) 9> mfem-data.lock
|
||||
#
|
||||
# Setup ${AUTOTEST_ROOT}/autotest:
|
||||
#
|
||||
- echo "AUTOTEST_ROOT ${AUTOTEST_ROOT}"
|
||||
- mkdir -p ${AUTOTEST_ROOT} && cd ${AUTOTEST_ROOT}
|
||||
- |
|
||||
(
|
||||
date
|
||||
echo "Waiting to acquire lock on '$PWD/autotest.lock' ..."
|
||||
# try to get an exclusive lock on fd 9 (autotest.lock) repeating the try
|
||||
# every 5 seconds; we may want to add a counter for the number of
|
||||
# retries to interrupt a potential infinite loop
|
||||
while ! flock -n 9; do
|
||||
sleep 5
|
||||
done
|
||||
echo "Acquired lock on '$PWD/autotest.lock'"
|
||||
date
|
||||
# clone/update the autotest repo while holding the file lock on
|
||||
# 'autotest.lock'
|
||||
err=0
|
||||
if [[ ! -d "autotest" ]]; then
|
||||
git clone ${AUTOTEST_REPO}
|
||||
else
|
||||
cd autotest && git pull && cd ..
|
||||
fi || err=1
|
||||
# sleep for a period to allow NFS to propagate the above changes;
|
||||
# clearly, there is no guarantee that other NFS clients will see the
|
||||
# changes even after the timeout
|
||||
sleep 10
|
||||
exit $err
|
||||
) 9> autotest.lock
|
||||
@@ -0,0 +1,67 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
stages:
|
||||
- setup
|
||||
- allocate_resource
|
||||
- build_and_test
|
||||
- release_resource_and_report
|
||||
|
||||
# Slurm shared allocation
|
||||
allocate_resource:
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
extends: .on_corona
|
||||
stage: allocate_resource
|
||||
script:
|
||||
- echo ${ALLOC_NAME}
|
||||
- salloc --exclusive --nodes=1 --partition=mi60 --time=45 --no-shell --job-name=${ALLOC_NAME}
|
||||
timeout: 6h
|
||||
needs: [setup]
|
||||
|
||||
# Build and test jobs, simply provide a spec
|
||||
rocm_gcc_8.3.1:
|
||||
variables:
|
||||
SPEC: "@develop%gcc@8.3.1+rocm amdgpu_target=gfx906"
|
||||
extends: .build_and_test_on_corona
|
||||
needs: [allocate_resource]
|
||||
|
||||
# Release slurm allocation
|
||||
release_resource:
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
extends: .on_corona
|
||||
stage: release_resource_and_report
|
||||
script:
|
||||
- echo ${ALLOC_NAME}
|
||||
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
|
||||
- echo ${JOBID}
|
||||
- ([[ -n "${JOBID}" ]] && scancel ${JOBID})
|
||||
needs: [rocm_gcc_8.3.1]
|
||||
|
||||
# Jobs report
|
||||
report_job_success:
|
||||
stage: release_resource_and_report
|
||||
extends:
|
||||
- .on_corona
|
||||
- .report_job_success
|
||||
|
||||
report_job_failure:
|
||||
stage: release_resource_and_report
|
||||
extends:
|
||||
- .on_corona
|
||||
- .report_job_failure
|
||||
|
||||
include:
|
||||
- local: .gitlab/configs/common.yml
|
||||
- local: .gitlab/configs/corona-config.yml
|
||||
- local: .gitlab/configs/setup-build-and-test.yml
|
||||
- local: .gitlab/configs/report-build-and-test.yml
|
||||
@@ -1,132 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
include:
|
||||
- project: 'lc-templates/id_tokens'
|
||||
file: 'id_tokens.yml'
|
||||
|
||||
# We define the following GitLab pipeline variables:
|
||||
variables:
|
||||
# Set the build-and-test command.
|
||||
# Nested variables are allowed and useful to customize the job command. We
|
||||
# protect variables with quotes so that their value may remain a string even if
|
||||
# they contain whitespaces.
|
||||
JOB_CMD:
|
||||
value: tests/gitlab/build_and_test --spec \"${SPEC}\" --data-dir ${MFEM_DATA_DIR} --data
|
||||
# The path to the shared resource between all jobs in the 'dane-baseline'
|
||||
# pipeline. For example, external repositories like 'tests' and 'tpls' are
|
||||
# cloned here. Also, 'tpls' is built once for all targets, so that build happens
|
||||
# here. The BUILD_ROOT is unique to the pipeline, preventing any form of
|
||||
# concurrency with other pipelines. This directory is removed by the 'cleanup'
|
||||
# stage in the 'dane-baseline' pipeline.
|
||||
BUILD_ROOT: ${USER_CI_TOP_DIR}/${CI_PROJECT_NAME}-${CI_MACHINE}-pipeline-${CI_PIPELINE_ID}
|
||||
|
||||
# On LLNL's dane and tioga, the 'build-and-test' pipelines creates only one
|
||||
# allocation shared among jobs in the pipeline in order to save time and
|
||||
# resources. This allocation has to be uniquely named so that we are sure to
|
||||
# retrieve it and avoid collisions.
|
||||
ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID}
|
||||
|
||||
# Git repositories used in the pipelines:
|
||||
# - TPLS_REPO and TESTS_REPO are used only by the 'dane-baseline' pipeline
|
||||
# - AUTOTEST_REPO is used by all pipelines
|
||||
# - MFEM_DATA_REPO is used only by the 'build-and-test' pipelines
|
||||
TPLS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tpls.git
|
||||
TESTS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tests.git
|
||||
AUTOTEST_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/autotest.git
|
||||
MFEM_DATA_REPO: https://github.com/mfem/data.git
|
||||
|
||||
# Directory used to place artifacts:
|
||||
# - ARTIFACTS_DIR is only used by the 'dane-baseline' pipeline
|
||||
ARTIFACTS_DIR: artifacts
|
||||
SLURM_OVERLAP: 1
|
||||
|
||||
# Dane
|
||||
# Arguments for top level allocation
|
||||
DANE_SHARED_ALLOC: "--exclusive --reservation=ci --time=60 --nodes=1"
|
||||
# Arguments for job level allocation
|
||||
# Note: We repeat the reservation, necessary when jobs are manually re-triggered.
|
||||
DANE_JOB_ALLOC: "--reservation=ci --overlap --nodes=1"
|
||||
|
||||
# Tioga
|
||||
# Arguments for top level allocation
|
||||
TIOGA_SHARED_ALLOC: "--queue=pci --exclusive --time-limit=45m --nodes=1"
|
||||
# Arguments for job level allocation
|
||||
TIOGA_JOB_ALLOC: "--nodes=1 --begin-time=+5s"
|
||||
|
||||
# Matrix
|
||||
# Arguments for top level allocation
|
||||
MATRIX_SHARED_ALLOC: "-p pdebug --exclusive --time=45 --nodes=1 -G 4"
|
||||
# Arguments for job level allocation
|
||||
# Note: We repeat the reservation, necessary when jobs are manually re-triggered.
|
||||
MATRIX_JOB_ALLOC: "--overlap --nodes=1"
|
||||
|
||||
# Configuration shared by build and test jobs specific to this project.
|
||||
# Not all configuration can be shared. Here projects can fine tune the
|
||||
# CI behavior.
|
||||
# See Umpire for an example (export junit test reports).
|
||||
.custom_job:
|
||||
artifacts:
|
||||
reports:
|
||||
|
||||
# Note: this part is not used by the 'dane-baseline' pipeline.
|
||||
# FIXME: BUILD_ROOT, TPLS_REPO, TESTS_REPO are not needed here.
|
||||
# Also, the definition of SHARED_REPOS_DIR is wrong.
|
||||
.reproducer_vars:
|
||||
script:
|
||||
- |
|
||||
echo -e "
|
||||
# Variables \n
|
||||
export SPEC=\"${SPEC//\"/\\\"}\" \n
|
||||
# Directories \n
|
||||
export BUILD_ROOT=\"\${working_dir}\" \n
|
||||
export SHARED_REPOS_DIR=\"\${BUILD_ROOT}/..\" \n
|
||||
export MFEM_DATA_DIR=\"\${SHARED_REPOS_DIR}/mfem-data\" \n
|
||||
# Repositories \n
|
||||
export TPLS_REPO=\"${TPLS_REPO//\"/\\\"}\" \n
|
||||
export TESTS_REPO=\"${TESTS_REPO//\"/\\\"}\" \n
|
||||
export AUTOTEST_REPO=\"${AUTOTEST_REPO//\"/\\\"}\" \n
|
||||
export MFEM_DATA_REPO=\"${MFEM_DATA_REPO//\"/\\\"}\" \n
|
||||
# Setup directories \n
|
||||
./tests/gitlab/build_and_test_setup \n
|
||||
# Using the CI build cache is optional and requires a token. Set it like so: \n
|
||||
# export REGISTRY_TOKEN=\"<your token here>\" \n"
|
||||
#
|
||||
|
||||
# Jobs report
|
||||
.report_job_success:
|
||||
script:
|
||||
- ${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test SUCCESS
|
||||
rules:
|
||||
- when: on_success
|
||||
|
||||
.report_job_failure:
|
||||
script:
|
||||
- ${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test FAILURE
|
||||
rules:
|
||||
- when: on_failure
|
||||
|
||||
# Keep the following for debugging purposes: renaming this job from
|
||||
# '.show_variables' to 'show_variables' will insert this debug job at the
|
||||
# beginning of all child pipelines.
|
||||
.show_variables:
|
||||
tags: [shell, oslic]
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
stage: .pre
|
||||
script:
|
||||
- |
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "AUTOTEST=${AUTOTEST}"
|
||||
echo "AUTOTEST_COMMIT=${AUTOTEST_COMMIT}"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
# Fail the job on purpose to prevent the rest of the pipeline from running
|
||||
false
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
variables:
|
||||
BASELINE_TEST: baseline
|
||||
MACHINE_NAME: dane
|
||||
|
||||
stages:
|
||||
- setup
|
||||
@@ -20,25 +19,6 @@ stages:
|
||||
- cleanup
|
||||
- baseline_publish
|
||||
|
||||
.on_dane:
|
||||
tags:
|
||||
- shell
|
||||
- dane
|
||||
rules:
|
||||
# Don't run dane jobs if...
|
||||
- if: '$ON_DANE == "OFF"'
|
||||
when: never
|
||||
# Don't run autotest update if...
|
||||
# Note: in some cases, the content of AUTOTEST can be '${AUTOTEST}', so we
|
||||
# need to treat that value as the default value of 'OFF'.
|
||||
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "ON" && $AUTOTEST != "YES"'
|
||||
when: never
|
||||
# Always cleanup
|
||||
- if: '$CI_JOB_NAME =~ /cleanup/'
|
||||
when: always
|
||||
# Default is to run if previous stage succeeded
|
||||
- when: on_success
|
||||
|
||||
baselinecheck_mfem_intel_dane:
|
||||
extends: [.on_dane]
|
||||
stage: baseline_check
|
||||
@@ -49,9 +29,6 @@ baselinecheck_mfem_intel_dane:
|
||||
# .gitlab/configs/setup-baseline.yml.
|
||||
TPLS_DIR: ${BUILD_ROOT}/tpls
|
||||
script:
|
||||
- echo "AUTOTEST=$AUTOTEST"
|
||||
- echo "AUTOTEST_COMMIT=$AUTOTEST_COMMIT"
|
||||
- echo "AUTOTEST_ROOT=$AUTOTEST_ROOT"
|
||||
- echo ${BUILD_ROOT}
|
||||
- echo ${TPLS_DIR}
|
||||
# Used by the tests in MFEM/tests, dane has 224 threads/node:
|
||||
@@ -112,13 +89,7 @@ report_baseline:
|
||||
cp ${rundir}/pipeline.txt ${rundir}/autotest-email.html
|
||||
fi
|
||||
msg="GitLab CI log for ${BASELINE_TEST} on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
|
||||
# Note: in some cases, the content of AUTOTEST_COMMIT can be
|
||||
# '${AUTOTEST_COMMIT}', so we need to treat that value as the default
|
||||
# value of 'ON'.
|
||||
if [[ "$AUTOTEST_COMMIT" == '${AUTOTEST_COMMIT}' ]]; then
|
||||
AUTOTEST_COMMIT="ON"
|
||||
fi
|
||||
if [[ "$AUTOTEST_COMMIT" == "ON" || "$AUTOTEST_COMMIT" == "YES" ]]; then
|
||||
if [[ "$AUTOTEST_COMMIT" != "NO" ]]; then
|
||||
git pull && \
|
||||
git add ${rundir} && \
|
||||
git commit -m "${msg}" && \
|
||||
@@ -146,8 +117,8 @@ baselinepublish_mfem_dane:
|
||||
extends: [.on_dane]
|
||||
stage: baseline_publish
|
||||
rules:
|
||||
# - if: '$CI_COMMIT_BRANCH == "master" || $REBASELINE == "ON"'
|
||||
- if: '$REBASELINE == "ON"'
|
||||
# - if: '$CI_COMMIT_BRANCH == "master" || $REBASELINE == "YES"'
|
||||
- if: '$REBASELINE == "YES"'
|
||||
when: manual
|
||||
script:
|
||||
- echo ${BUILD_ROOT}
|
||||
@@ -157,5 +128,6 @@ baselinepublish_mfem_dane:
|
||||
- .gitlab/scripts/rebaseline
|
||||
|
||||
include:
|
||||
- local: .gitlab/custom-jobs-and-variables.yml
|
||||
- local: .gitlab/configs/common.yml
|
||||
- local: .gitlab/configs/dane-config.yml
|
||||
- local: .gitlab/configs/setup-baseline.yml
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
stages:
|
||||
- setup
|
||||
- allocate_resource
|
||||
- build_and_test
|
||||
- release_resource_and_report
|
||||
|
||||
# Allocate
|
||||
allocate_resource:
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
extends: .on_dane
|
||||
stage: allocate_resource
|
||||
script:
|
||||
- echo ${ALLOC_NAME}
|
||||
- salloc --exclusive --nodes=1 --reservation=ci --time=60 --no-shell --job-name=${ALLOC_NAME}
|
||||
timeout: 6h
|
||||
|
||||
# GitLab jobs for the Dane machine at LLNL
|
||||
debug_ser_gcc_10:
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +debug~mpi"
|
||||
extends: .build_and_test_on_dane
|
||||
|
||||
debug_par_gcc_10:
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +debug+mpi"
|
||||
extends: .build_and_test_on_dane
|
||||
|
||||
opt_ser_gcc_10:
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 ~mpi"
|
||||
extends: .build_and_test_on_dane
|
||||
|
||||
opt_par_gcc_10:
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1"
|
||||
extends: .build_and_test_on_dane
|
||||
|
||||
opt_par_gcc_10_sundials:
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +sundials"
|
||||
extends: .build_and_test_on_dane
|
||||
|
||||
opt_par_gcc_10_petsc:
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +petsc ^petsc+mumps~superlu-dist"
|
||||
extends: .build_and_test_on_dane
|
||||
|
||||
opt_par_gcc_10_pumi:
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +pumi"
|
||||
extends: .build_and_test_on_dane
|
||||
|
||||
# Release
|
||||
release_resource:
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
extends: .on_dane
|
||||
stage: release_resource_and_report
|
||||
script:
|
||||
- echo ${ALLOC_NAME}
|
||||
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
|
||||
- echo ${JOBID}
|
||||
- ([[ -n "${JOBID}" ]] && scancel ${JOBID})
|
||||
|
||||
# Jobs report
|
||||
report_job_success:
|
||||
stage: release_resource_and_report
|
||||
extends:
|
||||
- .on_dane
|
||||
- .report_job_success
|
||||
|
||||
report_job_failure:
|
||||
stage: release_resource_and_report
|
||||
extends:
|
||||
- .on_dane
|
||||
- .report_job_failure
|
||||
|
||||
include:
|
||||
- local: .gitlab/configs/common.yml
|
||||
- local: .gitlab/configs/dane-config.yml
|
||||
- local: .gitlab/configs/setup-build-and-test.yml
|
||||
- local: .gitlab/configs/report-build-and-test.yml
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Jobs report
|
||||
report_job_success:
|
||||
extends: [.on_dane, .report_job_success]
|
||||
stage: jobs-stage-3
|
||||
|
||||
report_job_failure:
|
||||
extends: [.on_dane, .report_job_failure]
|
||||
stage: jobs-stage-3
|
||||
@@ -1,87 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Override reproducer section to define MFEM specific variables.
|
||||
.dane_reproducer_vars:
|
||||
script:
|
||||
- !reference [.reproducer_vars, script]
|
||||
|
||||
# TODO: Setup script should be defined as a bash script (but then GIT_STRATEGY
|
||||
# cannot be "none" anymore).
|
||||
|
||||
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
|
||||
# script then symlinks the repo to the parent directory of the MFEM source
|
||||
# directory. Unit tests that depend on the mfem/data repo will then detect that
|
||||
# this directory is present and be enabled.
|
||||
setup:
|
||||
extends: .on_dane
|
||||
stage: jobs-stage-1
|
||||
script:
|
||||
- ./tests/gitlab/build_and_test_setup
|
||||
|
||||
|
||||
########################
|
||||
# Overridden shared jobs
|
||||
########################
|
||||
# When using shared jobs, we can duplicate them here to override description and
|
||||
# add necessary changes.
|
||||
# We keep ${PROJECT_<MACHINE>_VARIANTS} and ${PROJECT_<MACHINE>_DEPS} So that
|
||||
# the comparison with the original job is easier.
|
||||
|
||||
|
||||
############
|
||||
# Extra jobs
|
||||
############
|
||||
# We do not recommend using ${PROJECT_<MACHINE>_VARIANTS} and
|
||||
# ${PROJECT_<MACHINE>_DEPS} in the extra jobs. There is not reason not to fully
|
||||
# describe the spec here.
|
||||
|
||||
.mfem_job_on_dane:
|
||||
extends: .job_on_dane
|
||||
stage: jobs-stage-2
|
||||
variables:
|
||||
# Dane has 224 threads/node and we run 7 separate jobs: 224=7*32
|
||||
THREADS: 28
|
||||
|
||||
debug_ser_gcc_10:
|
||||
extends: .mfem_job_on_dane
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +debug~mpi"
|
||||
|
||||
debug_par_gcc_10:
|
||||
extends: .mfem_job_on_dane
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +debug+mpi"
|
||||
|
||||
opt_ser_gcc_10:
|
||||
extends: .mfem_job_on_dane
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 ~mpi"
|
||||
|
||||
opt_par_gcc_10:
|
||||
extends: .mfem_job_on_dane
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1"
|
||||
|
||||
opt_par_gcc_10_sundials:
|
||||
extends: .mfem_job_on_dane
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +sundials"
|
||||
|
||||
opt_par_gcc_10_petsc:
|
||||
extends: .mfem_job_on_dane
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +petsc ^petsc+mumps~superlu-dist"
|
||||
|
||||
opt_par_gcc_10_pumi:
|
||||
extends: .mfem_job_on_dane
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +pumi"
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Jobs report
|
||||
report_job_success:
|
||||
extends: [.on_matrix, .report_job_success]
|
||||
stage: jobs-stage-3
|
||||
|
||||
report_job_failure:
|
||||
extends: [.on_matrix, .report_job_failure]
|
||||
stage: jobs-stage-3
|
||||
@@ -1,65 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Override reproducer section to define UMPIRE specific variables.
|
||||
.matrix_reproducer_vars:
|
||||
script:
|
||||
- !reference [.reproducer_vars, script]
|
||||
|
||||
#TODO: Setup script should be defined as a bash script (but then GIT_STRATEGY cannot be "none" anymore).
|
||||
|
||||
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
|
||||
# script then symlinks the repo to the parent directory of the MFEM source
|
||||
# directory. Unit tests that depend on the mfem/data repo will then detect that
|
||||
# this directory is present and be enabled.
|
||||
setup:
|
||||
extends: .on_matrix
|
||||
stage: jobs-stage-1
|
||||
script:
|
||||
- ./tests/gitlab/build_and_test_setup
|
||||
|
||||
|
||||
########################
|
||||
# Overridden shared jobs
|
||||
########################
|
||||
# When using shared jobs , we can duplicate them here to override description and add necessary changes.
|
||||
# We keep ${PROJECT_<MACHINE>_VARIANTS} and ${PROJECT_<MACHINE>_DEPS} So that
|
||||
# the comparison with the original job is easier.
|
||||
|
||||
|
||||
############
|
||||
# Extra jobs
|
||||
############
|
||||
# We do not recommend using ${PROJECT_<MACHINE>_VARIANTS} and
|
||||
# ${PROJECT_<MACHINE>_DEPS} in the extra jobs. There is not reason not to fully
|
||||
# describe the spec here.
|
||||
|
||||
.mfem_job_on_matrix:
|
||||
extends: .job_on_matrix
|
||||
stage: jobs-stage-2
|
||||
variables:
|
||||
# We run 2 jobs on 1 node that has 112 threads
|
||||
THREADS: 48
|
||||
# These modules need to be consistent with the uberenv configurations:
|
||||
MODULE_LIST: "gcc/10.3.1-magic cuda/12.9.1"
|
||||
|
||||
allocate_resources:
|
||||
timeout: 4h
|
||||
|
||||
opt_mpi_cuda_gcc:
|
||||
extends: .mfem_job_on_matrix
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +mpi +cuda cuda_arch=90"
|
||||
|
||||
opt_mpi_cuda_hypre_cuda_gcc:
|
||||
extends: .mfem_job_on_matrix
|
||||
variables:
|
||||
SPEC: "%gcc@10.3.1 +mpi +cuda cuda_arch=90 ^hypre+cuda"
|
||||
@@ -1,20 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Jobs report
|
||||
report_job_success:
|
||||
extends: [.on_tioga, .report_job_success]
|
||||
stage: jobs-stage-3
|
||||
|
||||
report_job_failure:
|
||||
extends: [.on_tioga, .report_job_failure]
|
||||
stage: jobs-stage-3
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Override reproducer section to define UMPIRE specific variables.
|
||||
.tioga_reproducer_vars:
|
||||
script:
|
||||
- !reference [.reproducer_vars, script]
|
||||
|
||||
#TODO: Setup script should be defined as a bash script (but then GIT_STRATEGY cannot be "none" anymore).
|
||||
|
||||
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
|
||||
# script then symlinks the repo to the parent directory of the MFEM source
|
||||
# directory. Unit tests that depend on the mfem/data repo will then detect that
|
||||
# this directory is present and be enabled.
|
||||
setup:
|
||||
extends: .on_tioga
|
||||
stage: jobs-stage-1
|
||||
script:
|
||||
- ./tests/gitlab/build_and_test_setup
|
||||
|
||||
########################
|
||||
# Overridden shared jobs
|
||||
########################
|
||||
# When using shared jobs , we can duplicate them here to override description and add necessary changes.
|
||||
# We keep ${PROJECT_<MACHINE>_VARIANTS} and ${PROJECT_<MACHINE>_DEPS} So that
|
||||
# the comparison with the original job is easier.
|
||||
|
||||
|
||||
############
|
||||
# Extra jobs
|
||||
############
|
||||
# We do not recommend using ${PROJECT_<MACHINE>_VARIANTS} and
|
||||
# ${PROJECT_<MACHINE>_DEPS} in the extra jobs. There is not reason not to fully
|
||||
# describe the spec here.
|
||||
|
||||
# Build and test jobs, simply provide a spec
|
||||
|
||||
#.tioga_job_command:
|
||||
# script:
|
||||
# - echo PROXY="${PROXY}"
|
||||
# - echo TIOGA_JOB_ALLOC="${TIOGA_JOB_ALLOC}"
|
||||
# - "printf '#!/bin/bash\n%s\n' \"${JOB_CMD}\" > flux_script.sh"
|
||||
# - cat flux_script.sh
|
||||
# - ${PROXY} flux watch $( ${PROXY} flux batch -o output.stdout.type=kvs ${TIOGA_JOB_ALLOC} flux_script.sh )
|
||||
# - rm -f flux_script.sh
|
||||
|
||||
.mfem_job_on_tioga:
|
||||
extends: .job_on_tioga
|
||||
stage: jobs-stage-2
|
||||
variables:
|
||||
# We run 1 job on 1 node that has 64 threads
|
||||
THREADS: 64
|
||||
|
||||
opt_mpi_rocm_hypre_rocm:
|
||||
extends: .mfem_job_on_tioga
|
||||
variables:
|
||||
SPEC: "%rocmcc@=6.3.1 +rocm amdgpu_target=gfx90a ^hypre+rocm"
|
||||
|
||||
# cce_16_0_1:
|
||||
# extends: .mfem_job_on_tioga
|
||||
# variables:
|
||||
# SPEC: "%cce@=16.0.1"
|
||||
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
stages:
|
||||
- setup
|
||||
- build_and_test
|
||||
- report
|
||||
|
||||
opt_mpi_cuda_gcc:
|
||||
variables:
|
||||
SPEC: "%gcc@8.3.1 +mpi +cuda cuda_arch=70"
|
||||
extends: .build_and_test_on_lassen
|
||||
|
||||
opt_mpi_cuda_hypre_cuda_gcc:
|
||||
variables:
|
||||
SPEC: "%gcc@8.3.1 +mpi +cuda cuda_arch=70 ^hypre+cuda~shared cuda_arch=70"
|
||||
extends: .build_and_test_on_lassen
|
||||
|
||||
# Jobs report
|
||||
report_job_success:
|
||||
stage: report
|
||||
extends:
|
||||
- .on_lassen
|
||||
- .report_job_success
|
||||
|
||||
report_job_failure:
|
||||
stage: report
|
||||
extends:
|
||||
- .on_lassen
|
||||
- .report_job_failure
|
||||
|
||||
include:
|
||||
- local: .gitlab/configs/common.yml
|
||||
- local: .gitlab/configs/lassen-config.yml
|
||||
- local: .gitlab/configs/setup-build-and-test.yml
|
||||
- local: .gitlab/configs/report-build-and-test.yml
|
||||
@@ -35,6 +35,8 @@ if [[ "${MACHINE_NAME}" == "dane" ]]; then
|
||||
salloc --nodes=1 --exclusive --reservation=ci ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
|
||||
elif [[ ${MACHINE_NAME} == "corona" ]]; then
|
||||
salloc --nodes=1 -t 60 -p pbatch ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
|
||||
elif [[ ${MACHINE_NAME} == "lassen" ]]; then
|
||||
lalloc 1 -q pci ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
|
||||
else
|
||||
echo "Unknown machine: MACHINE_NAME=$MACHINE_NAME"
|
||||
exit 1
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
function info_msg ()
|
||||
{
|
||||
echo "[Information:] ${1}"
|
||||
}
|
||||
|
||||
function error_msg ()
|
||||
{
|
||||
echo "[Error:] ${1}"
|
||||
}
|
||||
|
||||
# Perform a report while holding a lock file to prevent concurrency on
|
||||
# the destination.
|
||||
# Usage:
|
||||
# locked_clone <report_function> <lock_name>
|
||||
function locked_report ()
|
||||
{
|
||||
if ! command -v flock
|
||||
then
|
||||
error_msg "Required command 'flock' not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
info_msg "Will report ${1} while holding a lock in ${2}"
|
||||
|
||||
( date; info_msg "Waiting to acquire lock on '${PWD}/${2}.lock' ..."
|
||||
# try to get an exclusive lock on fd 9 (mfem-data.lock) repeating the
|
||||
# try every 5 seconds; we may want to add a counter for the number of
|
||||
# retries to interrupt a potential infinite loop
|
||||
while ! flock -n 9; do sleep 5; done
|
||||
date; info_msg "Acquired lock on '${PWD}/${2}.lock'"
|
||||
|
||||
report ${1}
|
||||
err=$?
|
||||
|
||||
# sleep for a period to allow NFS to propagate the above changes;
|
||||
# clearly, there is no guarantee that other NFS clients will see the
|
||||
# changes even after the timeout
|
||||
sleep 10
|
||||
exit $err
|
||||
) 9> ${2}.lock
|
||||
}
|
||||
|
||||
function report ()
|
||||
{
|
||||
if [[ "${1}" == "SUCCESS" ]]
|
||||
then
|
||||
info_msg "All the ${MACHINE_NAME} jobs passed"
|
||||
status_msg="The 'build-and-test' jobs on ${MACHINE_NAME} were SUCCESSFUL."
|
||||
elif [[ "${1}" == "FAILURE" ]]
|
||||
then
|
||||
info_msg "At least one failure on ${MACHINE_NAME}"
|
||||
status_msg="Some 'build-and-test' jobs on ${MACHINE_NAME} FAILED."
|
||||
else
|
||||
error_msg "Unknown status: ${1} ... aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd ${AUTOTEST_ROOT}/autotest || \
|
||||
{ error_msg "Invalid 'autotest' dir: ${AUTOTEST_ROOT}/autotest"; exit 1; }
|
||||
mkdir -p ${MACHINE_NAME}
|
||||
|
||||
rundir="${MACHINE_NAME}/$(date +%Y-%m-%d)-gitlab-ci-${CI_COMMIT_REF_SLUG}"
|
||||
rundir=$(${CI_PROJECT_DIR}/.gitlab/scripts/safe_create_rundir $rundir)
|
||||
|
||||
printf "%s\n" "${status_msg}" \
|
||||
"Pipeline URL:" "$CI_PIPELINE_URL" > ${rundir}/gitlab.err
|
||||
|
||||
msg="GitLab CI log for build-and-test on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
|
||||
|
||||
if [[ "${1}" == "FAILURE" ]]
|
||||
then
|
||||
# Create 'autotest-email.html' to indicate failure:
|
||||
cp ${rundir}/gitlab.err ${rundir}/autotest-email.html
|
||||
fi
|
||||
|
||||
# Note: in some cases, the content of AUTOTEST_COMMIT can be
|
||||
# '${AUTOTEST_COMMIT}', so we need to treat that value as the default
|
||||
# value of 'ON'.
|
||||
if [[ "$AUTOTEST_COMMIT" == '${AUTOTEST_COMMIT}' ]]; then
|
||||
AUTOTEST_COMMIT="ON"
|
||||
fi
|
||||
if [[ "$AUTOTEST_COMMIT" == "ON" || "$AUTOTEST_COMMIT" == "YES" ]]; then
|
||||
git pull && \
|
||||
git add ${rundir} && \
|
||||
git commit -m "${msg}" && \
|
||||
${CI_PROJECT_DIR}/.gitlab/scripts/git_try_to_push
|
||||
else
|
||||
for file in ${rundir}/*; do
|
||||
echo "------------------------------"
|
||||
echo "Content of '$file'"
|
||||
echo "******************************"
|
||||
cat $file
|
||||
echo "******************************"
|
||||
done
|
||||
rm -rf ${rundir} || true
|
||||
fi
|
||||
}
|
||||
|
||||
export MACHINE_NAME=${CI_MACHINE}
|
||||
info_msg "MACHINE_NAME is ${MACHINE_NAME}"
|
||||
info_msg "AUTOTEST_ROOT is ${AUTOTEST_ROOT}"
|
||||
info_msg "AUTOTEST=$AUTOTEST"
|
||||
info_msg "AUTOTEST_COMMIT=$AUTOTEST_COMMIT"
|
||||
|
||||
cd ${AUTOTEST_ROOT} && locked_report ${1} autotest
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
echo "Runs if there was at least one failure on ${MACHINE_NAME}"
|
||||
|
||||
cd ${AUTOTEST_ROOT}/autotest || \
|
||||
{ echo "Invalid 'autotest' dir: ${AUTOTEST_ROOT}/autotest"; exit 1; }
|
||||
mkdir -p ${MACHINE_NAME}
|
||||
|
||||
rundir="${MACHINE_NAME}/$(date +%Y-%m-%d)-gitlab-ci-${CI_COMMIT_REF_SLUG}"
|
||||
rundir=$(${CI_PROJECT_DIR}/.gitlab/scripts/safe_create_rundir $rundir)
|
||||
|
||||
printf "%s\n" "Some 'build-and-test' jobs on ${MACHINE_NAME} FAILED." \
|
||||
"Pipeline URL:" "$CI_PIPELINE_URL" > ${rundir}/gitlab.err
|
||||
|
||||
msg="GitLab CI log for build-and-test on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
|
||||
|
||||
# Create 'autotest-email.html' to indicate failure:
|
||||
cp ${rundir}/gitlab.err ${rundir}/autotest-email.html
|
||||
|
||||
if [[ "$AUTOTEST_COMMIT" != "NO" ]]; then
|
||||
git pull && \
|
||||
git add ${rundir} && \
|
||||
git commit -m "${msg}" && \
|
||||
${CI_PROJECT_DIR}/.gitlab/scripts/git_try_to_push
|
||||
else
|
||||
for file in ${rundir}/*; do
|
||||
echo "------------------------------"
|
||||
echo "Content of '$file'"
|
||||
echo "******************************"
|
||||
cat $file
|
||||
echo "******************************"
|
||||
done
|
||||
rm -rf ${rundir} || true
|
||||
fi
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
echo "Can only run if all the ${MACHINE_NAME} jobs passed"
|
||||
|
||||
cd ${AUTOTEST_ROOT}/autotest || \
|
||||
{ echo "Invalid 'autotest' dir: ${AUTOTEST_ROOT}/autotest"; exit 1; }
|
||||
mkdir -p ${MACHINE_NAME}
|
||||
|
||||
rundir="${MACHINE_NAME}/$(date +%Y-%m-%d)-gitlab-ci-${CI_COMMIT_REF_SLUG}"
|
||||
rundir=$(${CI_PROJECT_DIR}/.gitlab/scripts/safe_create_rundir $rundir)
|
||||
|
||||
printf "%s\n" "The 'build-and-test' jobs on ${MACHINE_NAME} were SUCCESSFUL." \
|
||||
"Pipeline URL:" "$CI_PIPELINE_URL" > ${rundir}/gitlab.out
|
||||
|
||||
msg="GitLab CI log for build-and-test on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
|
||||
|
||||
if [[ "$AUTOTEST_COMMIT" != "NO" ]]; then
|
||||
git pull && \
|
||||
git add ${rundir} && \
|
||||
git commit -m "${msg}" && \
|
||||
${CI_PROJECT_DIR}/.gitlab/scripts/git_try_to_push
|
||||
else
|
||||
for file in ${rundir}/*; do
|
||||
echo "------------------------------"
|
||||
echo "Content of '$file'"
|
||||
echo "******************************"
|
||||
cat $file
|
||||
echo "******************************"
|
||||
done
|
||||
rm -rf ${rundir} || true
|
||||
fi
|
||||
@@ -1,130 +0,0 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# The template job to test whether a machine is up.
|
||||
# Expects CI_MACHINE defined to machine name.
|
||||
.machine-check:
|
||||
stage: prerequisites
|
||||
tags: [shell, oslic]
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- |
|
||||
if [[ $(jq '.[env.CI_MACHINE].total_nodes_up' /usr/global/tools/lorenz/data/loginnodeStatus) == 0 ]]
|
||||
then
|
||||
echo -e "\e[31mNo node available on ${CI_MACHINE}\e[0m"
|
||||
false && \
|
||||
curl --url "https://api.github.com/repos/${GITHUB_PROJECT_ORG}/${GITHUB_PROJECT_NAME}/statuses/${CI_COMMIT_SHA}" \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header "authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--data "{ \"state\": \"failure\", \"target_url\": \"${CI_PIPELINE_URL}\", \"description\": \"GitLab ${CI_MACHINE} down\", \"context\": \"ci/gitlab/${CI_MACHINE}\" }"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
###
|
||||
# Trigger a build-and-test pipeline for a machine.
|
||||
# Comment the jobs for machines you don’t need.
|
||||
###
|
||||
|
||||
# One job to generate the job list for all the subpipelines
|
||||
generate-job-lists:
|
||||
stage: prerequisites
|
||||
tags: [shell, oslic]
|
||||
variables:
|
||||
LOCAL_JOBS_PATH: ".gitlab/jobs"
|
||||
script:
|
||||
- |
|
||||
echo "AUTOTEST=$AUTOTEST"
|
||||
echo "AUTOTEST_COMMIT=$AUTOTEST_COMMIT"
|
||||
echo "AUTOTEST_ROOT=$AUTOTEST_ROOT"
|
||||
- |
|
||||
cat ${LOCAL_JOBS_PATH}/dane.yml > dane-jobs.yml
|
||||
if [[ ${AUTOTEST} == "ON" || ${AUTOTEST} == "YES" ]]
|
||||
then
|
||||
cat ${LOCAL_JOBS_PATH}/dane-reports.yml >> dane-jobs.yml
|
||||
fi
|
||||
- |
|
||||
cat ${LOCAL_JOBS_PATH}/matrix.yml > matrix-jobs.yml
|
||||
if [[ ${AUTOTEST} == "ON" || ${AUTOTEST} == "YES" ]]
|
||||
then
|
||||
cat ${LOCAL_JOBS_PATH}/matrix-reports.yml >> matrix-jobs.yml
|
||||
fi
|
||||
- |
|
||||
cat ${LOCAL_JOBS_PATH}/tioga.yml > tioga-jobs.yml
|
||||
if [[ ${AUTOTEST} == "ON" || ${AUTOTEST} == "YES" ]]
|
||||
then
|
||||
cat ${LOCAL_JOBS_PATH}/tioga-reports.yml >> tioga-jobs.yml
|
||||
fi
|
||||
artifacts:
|
||||
paths:
|
||||
- dane-jobs.yml
|
||||
- matrix-jobs.yml
|
||||
- tioga-jobs.yml
|
||||
|
||||
|
||||
# DANE
|
||||
dane-up-check:
|
||||
variables:
|
||||
CI_MACHINE: "dane"
|
||||
extends: [.machine-check]
|
||||
|
||||
dane-build-and-test:
|
||||
variables:
|
||||
CI_MACHINE: "dane"
|
||||
needs: [dane-up-check, generate-job-lists]
|
||||
extends: [.build-and-test]
|
||||
|
||||
# DANE, MFEM Specific
|
||||
dane-baseline:
|
||||
stage: test-pipelines
|
||||
variables:
|
||||
# Explicitly pass down values that are not always propagated to child
|
||||
# pipelines, e.g. when a variable is set in the "Settings -> CI" web
|
||||
# interface (project variables).
|
||||
# Note: in some cases, this does not work as expected, e.g. when the
|
||||
# variable is not re-defined in the web interface; in such cases, the child
|
||||
# pipeline gets a definition like '${AUTOTEST}', i.e. it behaves as if
|
||||
# AUTOTEST is undefined, even though there is a default value in
|
||||
# .gitlab-ci.yml.
|
||||
AUTOTEST: "${AUTOTEST}"
|
||||
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
|
||||
trigger:
|
||||
include: .gitlab/dane-baseline.yml
|
||||
strategy: depend
|
||||
forward:
|
||||
pipeline_variables: true
|
||||
needs: [dane-up-check]
|
||||
|
||||
|
||||
# TIOGA
|
||||
tioga-up-check:
|
||||
variables:
|
||||
CI_MACHINE: "tioga"
|
||||
extends: [.machine-check]
|
||||
|
||||
tioga-build-and-test:
|
||||
variables:
|
||||
CI_MACHINE: "tioga"
|
||||
needs: [tioga-up-check, generate-job-lists]
|
||||
extends: [.build-and-test]
|
||||
|
||||
|
||||
# Matrix
|
||||
matrix-up-check:
|
||||
variables:
|
||||
CI_MACHINE: "matrix"
|
||||
extends: [.machine-check]
|
||||
|
||||
matrix-build-and-test:
|
||||
variables:
|
||||
CI_MACHINE: "matrix"
|
||||
needs: [matrix-up-check, generate-job-lists]
|
||||
extends: [.build-and-test]
|
||||
@@ -40,6 +40,8 @@ Discretization improvements
|
||||
provided that neighboring hexahedra are not refined in conflicting directions.
|
||||
A new ParMesh method is added to check for such conflicts, before refinement.
|
||||
|
||||
- Renamed the default GitHub branch from "master" to "main".
|
||||
|
||||
Meshing improvements
|
||||
--------------------
|
||||
|
||||
|
||||
+4
-4
@@ -652,7 +652,7 @@ if (MFEM_USE_CUDA)
|
||||
endif()
|
||||
|
||||
add_subdirectory(config)
|
||||
set(MASTER_HEADERS
|
||||
set(MAIN_HEADERS
|
||||
${PROJECT_SOURCE_DIR}/mfem.hpp
|
||||
${PROJECT_SOURCE_DIR}/mfem-performance.hpp)
|
||||
|
||||
@@ -689,7 +689,7 @@ set(MFEM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(MFEM_INSTALL_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
# Declaring the library
|
||||
mfem_add_library(mfem ${SOURCES} ${HEADERS} ${MASTER_HEADERS})
|
||||
mfem_add_library(mfem ${SOURCES} ${HEADERS} ${MAIN_HEADERS})
|
||||
# message(STATUS "TPL_LIBRARIES = ${TPL_LIBRARIES}")
|
||||
target_link_libraries(mfem PUBLIC ${TPL_LIBRARIES} ${TPL_TARGETS})
|
||||
if (TPL_TARGETS)
|
||||
@@ -888,12 +888,12 @@ install(TARGETS ${PROJECT_NAME}
|
||||
LIBRARY DESTINATION ${INSTALL_LIB_DIR}
|
||||
ARCHIVE DESTINATION ${INSTALL_LIB_DIR})
|
||||
|
||||
# Install the master headers
|
||||
# Install the main headers
|
||||
foreach(Header mfem.hpp mfem-performance.hpp)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/InstallHeaders/${Header}
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR})
|
||||
endforeach()
|
||||
install(FILES ${MASTER_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/mfem)
|
||||
install(FILES ${MAIN_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/mfem)
|
||||
|
||||
# Install the headers (except common miniapp which is installed from its subdir)
|
||||
install(DIRECTORY ${MFEM_SOURCE_DIRS}
|
||||
|
||||
+33
-33
@@ -3,10 +3,10 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/mfem/mfem/blob/master/LICENSE"><img alt="License" src="https://img.shields.io/badge/License-BSD-brightgreen.svg"></a>
|
||||
<a href="https://github.com/mfem/mfem/actions?query=workflow%3Arepo-check+branch%3Amaster"><img alt="Repo check" src="https://github.com/mfem/mfem/actions/workflows/repo-check.yml/badge.svg?branch=master"></a>
|
||||
<a href="https://github.com/mfem/mfem/actions?query=workflow%3Abuild-analysis+branch%3Amaster"><img alt="Build Analysis" src="https://github.com/mfem/mfem/actions/workflows/mfem-analysis.yml/badge.svg?branch=master"></a>
|
||||
<a href="https://github.com/mfem/mfem/actions?query=workflow%3Abuilds-and-tests+branch%3Amaster"><img alt="Builds and Tests" src="https://github.com/mfem/mfem/actions/workflows/builds-and-tests.yml/badge.svg?branch=master"></a>
|
||||
<a href="https://github.com/mfem/mfem/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/badge/License-BSD-brightgreen.svg"></a>
|
||||
<a href="https://github.com/mfem/mfem/actions?query=workflow%3Arepo-check+branch%3Amain"><img alt="Repo check" src="https://github.com/mfem/mfem/actions/workflows/repo-check.yml/badge.svg?branch=main"></a>
|
||||
<a href="https://github.com/mfem/mfem/actions?query=workflow%3Abuild-analysis+branch%3Amain"><img alt="Build Analysis" src="https://github.com/mfem/mfem/actions/workflows/mfem-analysis.yml/badge.svg?branch=main"></a>
|
||||
<a href="https://github.com/mfem/mfem/actions?query=workflow%3Abuilds-and-tests+branch%3Amain"><img alt="Builds and Tests" src="https://github.com/mfem/mfem/actions/workflows/builds-and-tests.yml/badge.svg?branch=main"></a>
|
||||
<a href="https://ci.appveyor.com/project/mfem/mfem"><img alt="Build Status" src="https://ci.appveyor.com/api/projects/status/19non9sqm6msi2wy?svg=true"></a>
|
||||
<a href="https://docs.mfem.org/html/index.html"><img alt="Doxygen" src="https://img.shields.io/badge/code-documented-brightgreen.svg"></a>
|
||||
</p>
|
||||
@@ -27,7 +27,7 @@ in the MFEM community, you agree to abide by its rules.
|
||||
If you plan on contributing to MFEM, consider reviewing the
|
||||
[issue tracker](https://github.com/mfem/mfem/issues) first to check if a thread
|
||||
already exists for your desired feature or the bug you ran into. Use a pull
|
||||
request (PR) toward the `mfem:master` branch to propose your contribution. If
|
||||
request (PR) toward the `mfem:main` branch to propose your contribution. If
|
||||
you are planning significant code changes or have questions, you may want to
|
||||
open an [issue](https://github.com/mfem/mfem/issues) before issuing a PR. In
|
||||
addition to technical contributions, we are also interested in your results and
|
||||
@@ -47,7 +47,7 @@ back to them before issuing pull requests:
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [MFEM PR Rules](#mfem-pr-rules)
|
||||
- [Pull Request Checklist](#pull-request-checklist)
|
||||
- [Master/Next Workflow](#masternext-workflow)
|
||||
- [Main/Next Workflow](#mainnext-workflow)
|
||||
- [Releases](#releases)
|
||||
- [Release Checklist](#release-checklist)
|
||||
- [LLNL Workflow](#llnl-workflow)
|
||||
@@ -66,12 +66,12 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
|
||||
## Quick Summary
|
||||
|
||||
- We encourage you to [join the MFEM organization](#mfem-organization) and create
|
||||
development branches off `mfem:master`.
|
||||
development branches off `mfem:main`.
|
||||
- Please follow the [developer guidelines](#developer-guidelines), in particular
|
||||
with regards to documentation and code styling.
|
||||
- Please do not commit large/binary files to the central repository (use a fork
|
||||
instead).
|
||||
- Pull requests should be issued toward `mfem:master`. Make sure
|
||||
- Pull requests should be issued toward `mfem:main`. Make sure
|
||||
to check the items off the [Pull Request Checklist](#pull-request-checklist) and
|
||||
follow the [MFEM PR Rules](#mfem-pr-rules).
|
||||
- When your contribution is fully working and ready to be reviewed, add
|
||||
@@ -81,8 +81,8 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
|
||||
- The reviewers have 3 weeks to evaluate the PR and work with the author to
|
||||
fix issues and implement improvements.
|
||||
- During review there should be no force pushes/rewriting history in the branch.
|
||||
- After approval, MFEM developers merge the PR manually in the [mfem:next branch](#masternext-workflow).
|
||||
- After a week of testing in `mfem:next`, the original PR is merged in `mfem:master`.
|
||||
- After approval, MFEM developers merge the PR manually in the [mfem:next branch](#mainnext-workflow).
|
||||
- After a week of testing in `mfem:next`, the original PR is merged in `mfem:main`.
|
||||
- We use [milestones](https://github.com/mfem/mfem/milestones) to coordinate the
|
||||
work on different PRs toward a release.
|
||||
- Don't hesitate to [contact us](#contact-information) if you have any questions.
|
||||
@@ -289,7 +289,7 @@ Before you can start, you need a GitHub account, here are a few suggestions:
|
||||
author, is willing to work on it and be its champion.
|
||||
|
||||
- The author creates a branch for the new feature (with suffix `-dev`), off
|
||||
the `master` branch, or another existing feature branch, for example:
|
||||
the `main` branch, or another existing feature branch, for example:
|
||||
|
||||
```
|
||||
# Clone assuming you have setup your ssh keys on GitHub:
|
||||
@@ -298,8 +298,8 @@ Before you can start, you need a GitHub account, here are a few suggestions:
|
||||
# Alternatively, clone using the "https" protocol:
|
||||
git clone https://github.com/mfem/mfem.git
|
||||
|
||||
# Create a new feature branch starting from "master":
|
||||
git checkout master
|
||||
# Create a new feature branch starting from "main":
|
||||
git checkout main
|
||||
git pull
|
||||
git checkout -b feature-dev
|
||||
|
||||
@@ -375,7 +375,7 @@ Before you can start, you need a GitHub account, here are a few suggestions:
|
||||
### Pull Requests
|
||||
|
||||
- When your branch is ready for other developers to review / comment on
|
||||
the code, create a pull request towards `mfem:master`.
|
||||
the code, create a pull request towards `mfem:main`.
|
||||
|
||||
- Pull request typically have titles like:
|
||||
|
||||
@@ -411,7 +411,7 @@ Before you can start, you need a GitHub account, here are a few suggestions:
|
||||
assigned, the PR is considered under review. To help with the review process
|
||||
there should be no force pushes/rewriting history in the branch.
|
||||
|
||||
- After approval, the PR is [tested](#masternext-workflow) for a week with
|
||||
- After approval, the PR is [tested](#mainnext-workflow) for a week with
|
||||
other approved PRs in the `mfem:next` branch.
|
||||
|
||||
- Consider manually running the tests in `tests/scripts` before merging in
|
||||
@@ -447,7 +447,7 @@ The Pull Request (PR) approval process in MFEM is similar to the approval of pap
|
||||
|
||||
3. A PR can be (manually) merged in the *next* branch only if 2 of the assigned reviewers have approved it and it has passed internal testing. This merge can be performed by any of the assigned reviewers or by any of the editors.
|
||||
|
||||
4. A PR can be merged in the *master* branch only if it has been tested successfully for a week in *next* and an editor has (optionally) taken a final look. This merge can be performed only by one of the editors.
|
||||
4. A PR can be merged in the *main* branch only if it has been tested successfully for a week in *next* and an editor has (optionally) taken a final look. This merge can be performed only by one of the editors.
|
||||
|
||||
#### Responsibilities of Editors
|
||||
|
||||
@@ -470,7 +470,7 @@ The current list of MFEM editors is:
|
||||
|
||||
5. To remind the reviewers about timely completion of their review.
|
||||
|
||||
6. To take a final look and complete the PR merge in *master*. The final look step is optional and shouldn't take more than 3 days.
|
||||
6. To take a final look and complete the PR merge in *main*. The final look step is optional and shouldn't take more than 3 days.
|
||||
|
||||
7. The assignment of bugfixes should be expedited proportional to their importance, e.g. in some cases the editor can assign much shorter review window.
|
||||
|
||||
@@ -492,7 +492,7 @@ Everyone on the MFEM team can be asked to serve as a reviewer on a PR in their a
|
||||
|
||||
5. To test the PR thoroughly before merging in *next*. The PR author is also encouraged to perform testing and inform the reviewers about the results.
|
||||
|
||||
6. To monitor the PR impact on the testing in the *next* branch and alert the editors that the PR is ready for merging in *master*.
|
||||
6. To monitor the PR impact on the testing in the *next* branch and alert the editors that the PR is ready for merging in *main*.
|
||||
|
||||
7. The review of bugfixes should be expedited proportional to their importance. The review window can be much less than three weeks in such cases.
|
||||
|
||||
@@ -582,11 +582,11 @@ Before a PR can be merged, it should satisfy the following:
|
||||
- [ ] Update internal tests to include the new features.
|
||||
|
||||
|
||||
### Master/Next Workflow
|
||||
### Main/Next Workflow
|
||||
|
||||
MFEM uses a `master`/`next`-branch workflow as described below:
|
||||
MFEM uses a `main`/`next`-branch workflow as described below:
|
||||
|
||||
- The `master` branch should always be of release quality and changes should not
|
||||
- The `main` branch should always be of release quality and changes should not
|
||||
be merged until they have been fully tested. This branch is protected, and
|
||||
changes can only be made through pull requests.
|
||||
|
||||
@@ -613,20 +613,20 @@ MFEM uses a `master`/`next`-branch workflow as described below:
|
||||
|
||||
- After a week of testing in `next` (excluding bugfixes), both on GitHub, as
|
||||
well as [internally](#tests-at-llnl) at LLNL, the original PR is merged into
|
||||
`master` (provided there are no issues).
|
||||
`main` (provided there are no issues).
|
||||
|
||||
- After the merge, the feature branch is deleted (unless it is a long-term
|
||||
project with periodic PRs).
|
||||
|
||||
- The `next` branch is used just for integrated testing of all PRs approved for
|
||||
merging into `master` to verify that each works individually and that all of
|
||||
merging into `main` to verify that each works individually and that all of
|
||||
them work as a group. This branch can be discarded at any time, though we
|
||||
typically do that only at the end of a [release cycle](#releases).
|
||||
|
||||
|
||||
### Releases
|
||||
|
||||
- Releases are just tags in the `master` branch, e.g. https://github.com/mfem/mfem/releases/tag/v3.3.2,
|
||||
- Releases are just tags in the `main` branch, e.g. https://github.com/mfem/mfem/releases/tag/v3.3.2,
|
||||
and have a version that ends in an even "patch" number, e.g. `v3.2.2` or
|
||||
`v3.4` (by convention `v3.4` is the same as `v3.4.0`.) Between releases, the
|
||||
version ends in an odd "patch" number, e.g. `v3.3.3`.
|
||||
@@ -679,19 +679,19 @@ MFEM uses a `master`/`next`-branch workflow as described below:
|
||||
|
||||
### Mirroring on Bitbucket
|
||||
|
||||
- The GitHub `master` and `next` branches are mirrored to the LLNL institutional
|
||||
Bitbucket repository as `gh-master` and `gh-next`.
|
||||
- The GitHub `main` and `next` branches are mirrored to the LLNL institutional
|
||||
Bitbucket repository as `gh-main` and `gh-next`.
|
||||
|
||||
- `gh-master` is merged into LLNL's internal `master` through pull requests; write
|
||||
permissions to `master` are restricted to ensure this is the only way in which it
|
||||
- `gh-main` is merged into LLNL's internal `main` through pull requests; write
|
||||
permissions to `main` are restricted to ensure this is the only way in which it
|
||||
gets updated.
|
||||
|
||||
- We never push directly from LLNL to GitHub.
|
||||
|
||||
- Versions of the code on LLNL's internal server, from most to least stable:
|
||||
- MFEM official release on mfem.org -- Most stable, tested in many apps.
|
||||
- `mfem:master` -- Recent development version, guaranteed to work.
|
||||
- `mfem:gh-master` -- Stable development version, passed testing, you can use
|
||||
- `mfem:main` -- Recent development version, guaranteed to work.
|
||||
- `mfem:gh-main` -- Stable development version, passed testing, you can use
|
||||
it to build your code between releases.
|
||||
- `mfem:gh-next` -- Bleeding-edge development version, may be broken, use at
|
||||
your own risk.
|
||||
@@ -721,14 +721,14 @@ directory.
|
||||
|
||||
|
||||
### Linux and Mac smoke tests
|
||||
We use GitHub Actions to drive the default tests on the `master` and `next`
|
||||
We use GitHub Actions to drive the default tests on the `main` and `next`
|
||||
branches. See the `.github/workflows` files and the logs at
|
||||
[https://github.com/mfem/mfem/actions](https://github.com/mfem/mfem/actions).
|
||||
|
||||
Testing using GitHub Actions should be kept lightweight, as there is a time
|
||||
constraint on jobs. Two virtual machines are configured - Mac (OS X) and Linux.
|
||||
|
||||
- Tests on the `master` branch are triggered whenever a PR is issued on this branch.
|
||||
- Tests on the `main` branch are triggered whenever a PR is issued on this branch.
|
||||
- Tests on the `next` branch are currently scheduled to run each night.
|
||||
|
||||
|
||||
@@ -744,7 +744,7 @@ and debug build is performed with a simple run of `ex1` to verify the executable
|
||||
|
||||
### Tests at LLNL
|
||||
|
||||
- We mirror the `master` and `next` branches internally (to `gh-master` and
|
||||
- We mirror the `main` and `next` branches internally (to `gh-main` and
|
||||
`gh-next`) and run longer nightly tests via cron. On the weekends, a more
|
||||
extensive test is run which extracts and executes all the different sample
|
||||
runs from each example and most miniapps.
|
||||
|
||||
@@ -33,8 +33,8 @@ RUN mkdir -p /opt/mfem-env \
|
||||
RUN cd /opt/mfem-env && \
|
||||
. /opt/spack/share/spack/setup-env.sh && \
|
||||
spack env activate . && \
|
||||
spack develop --path /code mfem@master+examples+miniapps && \
|
||||
spack add mfem@master+examples+miniapps && \
|
||||
spack develop --path /code mfem@main+examples+miniapps && \
|
||||
spack add mfem@main+examples+miniapps # && \
|
||||
spack install
|
||||
|
||||
# ensure mfem always on various paths
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
spack:
|
||||
specs: [mfem@master+examples+miniapps]
|
||||
view:
|
||||
specs: [mfem@main+examples+miniapps]
|
||||
view:
|
||||
mfem:
|
||||
root: /opt/mfem-view
|
||||
root: /opt/mfem-view
|
||||
link_type: copy
|
||||
concretization: together
|
||||
develop:
|
||||
mfem:
|
||||
path: /code
|
||||
spec: mfem@master+examples+miniapps
|
||||
spec: mfem@main+examples+miniapps
|
||||
|
||||
@@ -115,7 +115,7 @@ fi
|
||||
|
||||
# branch-history
|
||||
if [[ "${option}" == "--history" || "${option}" == "" ]]; then
|
||||
git fetch origin master:master
|
||||
git fetch origin main:main
|
||||
cd tests/scripts
|
||||
if ! ./runtest branch-history; then code=1; fi
|
||||
cd -
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Jupyter Notebooks using xeus-cling
|
||||
|
||||
[](https://mybinder.org/v2/gh/mfem/mfem/master?filepath=examples%2Fjupyter%2Fex.ipynb)
|
||||
[](https://mybinder.org/v2/gh/mfem/mfem/main?filepath=examples%2Fjupyter%2Fex.ipynb)
|
||||
|
||||
[xeus-cling](https://github.com/jupyter-xeus/xeus-cling) is a C++ Jupyter Kernel based on [cling](https://github.com/root-project/cling),
|
||||
which can be used to create interactive C++ MFEM and GLVis notebooks.
|
||||
|
||||
+5
-35
@@ -436,7 +436,7 @@ void NonlinearForm::Mult(const Vector &x, Vector &y) const
|
||||
// In parallel, the result is in 'py' which is an alias for 'aux2'.
|
||||
}
|
||||
|
||||
Operator &NonlinearForm::GetGradient(const Vector &x, bool finalize) const
|
||||
Operator &NonlinearForm::GetGradient(const Vector &x) const
|
||||
{
|
||||
if (ext)
|
||||
{
|
||||
@@ -644,8 +644,6 @@ Operator &NonlinearForm::GetGradient(const Vector &x, bool finalize) const
|
||||
}
|
||||
}
|
||||
|
||||
if (!finalize) { return *Grad; }
|
||||
|
||||
if (!Grad->Finalized())
|
||||
{
|
||||
Grad->Finalize(skip_zeros);
|
||||
@@ -1205,14 +1203,7 @@ const BlockVector &BlockNonlinearForm::Prolongate(const BlockVector &bx) const
|
||||
aux1.Update(block_offsets);
|
||||
for (int s = 0; s < fes.Size(); s++)
|
||||
{
|
||||
if (P[s])
|
||||
{
|
||||
P[s]->Mult(bx.GetBlock(s), aux1.GetBlock(s));
|
||||
}
|
||||
else
|
||||
{
|
||||
aux1.GetBlock(s) = bx.GetBlock(s);
|
||||
}
|
||||
P[s]->Mult(bx.GetBlock(s), aux1.GetBlock(s));
|
||||
}
|
||||
return aux1;
|
||||
}
|
||||
@@ -1241,16 +1232,11 @@ void BlockNonlinearForm::Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
cP[s]->MultTranspose(pby.GetBlock(s), by.GetBlock(s));
|
||||
}
|
||||
else if (needs_prolongation)
|
||||
{
|
||||
by.GetBlock(s) = pby.GetBlock(s);
|
||||
}
|
||||
by.GetBlock(s).SetSubVector(*ess_tdofs[s], 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
void BlockNonlinearForm::ComputeGradientBlocked(const BlockVector &bx,
|
||||
bool finalize) const
|
||||
void BlockNonlinearForm::ComputeGradientBlocked(const BlockVector &bx) const
|
||||
{
|
||||
const int skip_zeros = 0;
|
||||
Array<Array<int> *> vdofs(fes.Size());
|
||||
@@ -1504,7 +1490,7 @@ void BlockNonlinearForm::ComputeGradientBlocked(const BlockVector &bx,
|
||||
}
|
||||
}
|
||||
|
||||
if (finalize && !Grads(0,0)->Finalized())
|
||||
if (!Grads(0,0)->Finalized())
|
||||
{
|
||||
for (int i=0; i<fes.Size(); ++i)
|
||||
{
|
||||
@@ -1543,23 +1529,7 @@ Operator &BlockNonlinearForm::GetGradient(const Vector &x) const
|
||||
for (int s2 = 0; s2 < fes.Size(); ++s2)
|
||||
{
|
||||
delete cGrads(s1, s2);
|
||||
if (cP[s1] && cP[s2])
|
||||
{
|
||||
cGrads(s1, s2) = RAP(*cP[s1], *Grads(s1, s2), *cP[s2]);
|
||||
}
|
||||
else if (cP[s1])
|
||||
{
|
||||
cGrads(s1, s2) = TransposeMult(*cP[s1], *Grads(s1, s2));
|
||||
}
|
||||
else if (cP[s2])
|
||||
{
|
||||
cGrads(s1, s2) = mfem::Mult(*Grads(s1, s2), *cP[s2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cGrads(s1, s2) = NULL;
|
||||
continue;
|
||||
}
|
||||
cGrads(s1, s2) = RAP(*cP[s1], *Grads(s1, s2), *cP[s2]);
|
||||
mGrads(s1, s2) = cGrads(s1, s2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,12 +217,7 @@ public:
|
||||
In general, @a x may have non-homogeneous essential boundary values.
|
||||
|
||||
The state @a x must be a true-dof vector. */
|
||||
Operator &GetGradient(const Vector &x) const override { return GetGradient(x, true); }
|
||||
|
||||
/** @brief Compute the gradient Operator of the NonlinearForm corresponding
|
||||
to the state @a x with optional finalization and elimintaion. */
|
||||
/** @see GetGradient(const Vector &) */
|
||||
Operator &GetGradient(const Vector &x, bool finalize) const;
|
||||
Operator &GetGradient(const Vector &x) const override;
|
||||
|
||||
/// Update the NonlinearForm to propagate updates of the associated FE space.
|
||||
/** After calling this method, the essential boundary conditions need to be
|
||||
@@ -313,7 +308,7 @@ protected:
|
||||
void MultBlocked(const BlockVector &bx, BlockVector &by) const;
|
||||
|
||||
/// Specialized version of GetGradient() for BlockVector
|
||||
void ComputeGradientBlocked(const BlockVector &bx, bool finalize = true) const;
|
||||
void ComputeGradientBlocked(const BlockVector &bx) const;
|
||||
|
||||
public:
|
||||
/// Construct an empty BlockNonlinearForm. Initialize with SetSpaces().
|
||||
|
||||
+40
-252
@@ -151,15 +151,6 @@ void ParBilinearForm::ParallelRAP(SparseMatrix &loc_A, OperatorHandle &A,
|
||||
}
|
||||
}
|
||||
|
||||
HypreParMatrix *ParBilinearForm::ParallelAssembleInternalMatrix()
|
||||
{
|
||||
if (p_mat.Ptr() == NULL)
|
||||
{
|
||||
ParallelAssemble(p_mat, mat);
|
||||
}
|
||||
return p_mat.As<HypreParMatrix>();
|
||||
}
|
||||
|
||||
void ParBilinearForm::ParallelAssemble(OperatorHandle &A, SparseMatrix *A_local)
|
||||
{
|
||||
A.Clear();
|
||||
@@ -342,15 +333,6 @@ void ParBilinearForm
|
||||
A.EliminateRowsCols(dof_list, X, B);
|
||||
}
|
||||
|
||||
void ParBilinearForm::ParallelEliminateEssentialBC(
|
||||
const Array<int> &bdr_attr_is_ess, const HypreParVector &X, HypreParVector &B)
|
||||
{
|
||||
Array<int> dof_list;
|
||||
pfes->GetEssentialTrueDofs(bdr_attr_is_ess, dof_list);
|
||||
|
||||
p_mat.As<HypreParMatrix>()->EliminateRowsCols(dof_list, X, B);
|
||||
}
|
||||
|
||||
HypreParMatrix *ParBilinearForm::
|
||||
ParallelEliminateEssentialBC(const Array<int> &bdr_attr_is_ess,
|
||||
HypreParMatrix &A) const
|
||||
@@ -362,26 +344,6 @@ ParallelEliminateEssentialBC(const Array<int> &bdr_attr_is_ess,
|
||||
return A.EliminateRowsCols(dof_list);
|
||||
}
|
||||
|
||||
void ParBilinearForm::ParallelEliminateEssentialBC(const Array<int>
|
||||
&bdr_attr_is_ess)
|
||||
{
|
||||
Array<int> tdofs_list;
|
||||
pfes->GetEssentialTrueDofs(bdr_attr_is_ess, tdofs_list);
|
||||
|
||||
ParallelEliminateTDofs(tdofs_list);
|
||||
}
|
||||
|
||||
void ParBilinearForm::ParallelEliminateTDofs(const Array<int> &tdofs_list)
|
||||
{
|
||||
p_mat_e.EliminateRowsCols(p_mat, tdofs_list);
|
||||
}
|
||||
|
||||
void ParBilinearForm::ParallelEliminateTDofsInRHS(
|
||||
const Array<int> &tdofs_list, const Vector &x, Vector &b)
|
||||
{
|
||||
p_mat.EliminateBC(p_mat_e, tdofs_list, x, b);
|
||||
}
|
||||
|
||||
void ParBilinearForm::TrueAddMult(const Vector &x, Vector &y, const real_t a)
|
||||
const
|
||||
{
|
||||
@@ -523,7 +485,7 @@ void ParBilinearForm::FormLinearSystem(
|
||||
HypreParVector true_X(pfes), true_B(pfes);
|
||||
P.MultTranspose(b, true_B);
|
||||
R.Mult(x, true_X);
|
||||
ParallelEliminateTDofsInRHS(ess_tdof_list, true_X, true_B);
|
||||
p_mat.EliminateBC(p_mat_e, ess_tdof_list, true_X, true_B);
|
||||
R.MultTranspose(true_B, b);
|
||||
hybridization->ReduceRHS(true_B, B);
|
||||
X.SetSize(B.Size());
|
||||
@@ -536,11 +498,17 @@ void ParBilinearForm::FormLinearSystem(
|
||||
B.SetSize(X.Size());
|
||||
P.MultTranspose(b, B);
|
||||
R.Mult(x, X);
|
||||
ParallelEliminateTDofsInRHS(ess_tdof_list, X, B);
|
||||
p_mat.EliminateBC(p_mat_e, ess_tdof_list, X, B);
|
||||
if (!copy_interior) { X.SetSubVectorComplement(ess_tdof_list, 0.0); }
|
||||
}
|
||||
}
|
||||
|
||||
void ParBilinearForm::EliminateVDofsInRHS(
|
||||
const Array<int> &vdofs, const Vector &x, Vector &b)
|
||||
{
|
||||
p_mat.EliminateBC(p_mat_e, vdofs, x, b);
|
||||
}
|
||||
|
||||
void ParBilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
|
||||
OperatorHandle &A)
|
||||
{
|
||||
@@ -585,7 +553,7 @@ void ParBilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
|
||||
mat = NULL;
|
||||
delete mat_e;
|
||||
mat_e = NULL;
|
||||
ParallelEliminateTDofs(ess_tdof_list);
|
||||
p_mat_e.EliminateRowsCols(p_mat, ess_tdof_list);
|
||||
}
|
||||
if (hybridization)
|
||||
{
|
||||
@@ -647,180 +615,36 @@ void ParBilinearForm::Update(FiniteElementSpace *nfes)
|
||||
p_mat_e.Clear();
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::pAllocMat()
|
||||
{
|
||||
const int trial_nbr_size = trial_pfes->GetFaceNbrVSize();
|
||||
const int test_nbr_size = test_pfes->GetFaceNbrVSize();
|
||||
|
||||
if (keep_nbr_block)
|
||||
{
|
||||
mat = new SparseMatrix(height + test_nbr_size, width + trial_nbr_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
mat = new SparseMatrix(height, width + trial_nbr_size);
|
||||
}
|
||||
HypreParMatrix *ParMixedBilinearForm::ParallelAssemble()
|
||||
{
|
||||
// construct the block-diagonal matrix A
|
||||
HypreParMatrix *A =
|
||||
new HypreParMatrix(trial_pfes->GetComm(),
|
||||
test_pfes->GlobalVSize(),
|
||||
trial_pfes->GlobalVSize(),
|
||||
test_pfes->GetDofOffsets(),
|
||||
trial_pfes->GetDofOffsets(),
|
||||
mat);
|
||||
|
||||
HypreParMatrix *rap = RAP(test_pfes->Dof_TrueDof_Matrix(), A,
|
||||
trial_pfes->Dof_TrueDof_Matrix());
|
||||
|
||||
delete A;
|
||||
|
||||
return rap;
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::AssembleSharedFaces(int skip_zeros)
|
||||
void ParMixedBilinearForm::ParallelAssemble(OperatorHandle &A)
|
||||
{
|
||||
ParMesh *pmesh = trial_pfes->GetParMesh();
|
||||
FaceElementTransformations *T;
|
||||
Array<int> tr_vdofs1, tr_vdofs2, tr_vdofs_all;
|
||||
Array<int> te_vdofs1, te_vdofs2, te_vdofs_all;
|
||||
DenseMatrix elemmat;
|
||||
|
||||
int nfaces = pmesh->GetNSharedFaces();
|
||||
for (int i = 0; i < nfaces; i++)
|
||||
{
|
||||
T = pmesh->GetSharedFaceTransformations(i);
|
||||
int Elem2NbrNo = T->Elem2No - pmesh->GetNE();
|
||||
trial_pfes->GetElementVDofs(T->Elem1No, tr_vdofs1);
|
||||
test_pfes->GetElementVDofs(T->Elem1No, te_vdofs1);
|
||||
trial_pfes->GetFaceNbrElementVDofs(Elem2NbrNo, tr_vdofs2);
|
||||
test_pfes->GetFaceNbrElementVDofs(Elem2NbrNo, te_vdofs2);
|
||||
|
||||
tr_vdofs1.Copy(tr_vdofs_all);
|
||||
for (int j = 0; j < tr_vdofs2.Size(); j++)
|
||||
{
|
||||
if (tr_vdofs2[j] >= 0)
|
||||
{
|
||||
tr_vdofs2[j] += width;
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_vdofs2[j] -= width;
|
||||
}
|
||||
}
|
||||
tr_vdofs_all.Append(tr_vdofs2);
|
||||
|
||||
if (keep_nbr_block)
|
||||
{
|
||||
te_vdofs1.Copy(te_vdofs_all);
|
||||
for (int j = 0; j < te_vdofs2.Size(); j++)
|
||||
{
|
||||
if (te_vdofs2[j] >= 0)
|
||||
{
|
||||
te_vdofs2[j] += height;
|
||||
}
|
||||
else
|
||||
{
|
||||
te_vdofs2[j] -= height;
|
||||
}
|
||||
}
|
||||
te_vdofs_all.Append(te_vdofs2);
|
||||
}
|
||||
|
||||
for (int k = 0; k < interior_face_integs.Size(); k++)
|
||||
{
|
||||
interior_face_integs[k]->
|
||||
AssembleFaceMatrix(*trial_pfes->GetFE(T->Elem1No),
|
||||
*test_pfes->GetFE(T->Elem1No),
|
||||
*trial_pfes->GetFaceNbrFE(Elem2NbrNo),
|
||||
*test_pfes->GetFaceNbrFE(Elem2NbrNo),
|
||||
*T, elemmat);
|
||||
if (keep_nbr_block)
|
||||
{
|
||||
mat->AddSubMatrix(te_vdofs_all, tr_vdofs_all, elemmat, skip_zeros);
|
||||
}
|
||||
else
|
||||
{
|
||||
mat->AddSubMatrix(te_vdofs1, tr_vdofs_all, elemmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::Assemble(int skip_zeros)
|
||||
{
|
||||
if (interior_face_integs.Size())
|
||||
{
|
||||
trial_pfes->ExchangeFaceNbrData();
|
||||
test_pfes->ExchangeFaceNbrData();
|
||||
if (!ext && mat == NULL)
|
||||
{
|
||||
pAllocMat();
|
||||
}
|
||||
}
|
||||
|
||||
MixedBilinearForm::Assemble(skip_zeros);
|
||||
|
||||
if (!ext && interior_face_integs.Size() > 0)
|
||||
{
|
||||
AssembleSharedFaces(skip_zeros);
|
||||
}
|
||||
}
|
||||
|
||||
HypreParMatrix *ParMixedBilinearForm::ParallelAssembleInternalMatrix()
|
||||
{
|
||||
if (p_mat.Ptr() == NULL)
|
||||
{
|
||||
ParallelAssemble(p_mat, mat);
|
||||
}
|
||||
return p_mat.As<HypreParMatrix>();
|
||||
}
|
||||
|
||||
HypreParMatrix *ParMixedBilinearForm::ParallelAssemble(SparseMatrix *m)
|
||||
{
|
||||
OperatorHandle Mh(Operator::Hypre_ParCSR);
|
||||
ParallelAssemble(Mh, m);
|
||||
Mh.SetOperatorOwner(false);
|
||||
return Mh.As<HypreParMatrix>();
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::ParallelAssemble(OperatorHandle &A,
|
||||
SparseMatrix *A_local)
|
||||
{
|
||||
A.Clear();
|
||||
|
||||
if (A_local == NULL) { return; }
|
||||
MFEM_VERIFY(A_local->Finalized(), "the local matrix must be finalized");
|
||||
|
||||
OperatorHandle dA(A.Type()), hdA;
|
||||
|
||||
if (interior_face_integs.Size() == 0)
|
||||
{
|
||||
// construct the rectangular block-diagonal matrix dA
|
||||
dA.MakeRectangularBlockDiag(trial_pfes->GetComm(),
|
||||
test_pfes->GlobalVSize(),
|
||||
trial_pfes->GlobalVSize(),
|
||||
test_pfes->GetDofOffsets(),
|
||||
trial_pfes->GetDofOffsets(),
|
||||
A_local);
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle the case when 'a' contains off-diagonal
|
||||
const int lvrows = test_pfes->GetVSize();
|
||||
const int lvcols = trial_pfes->GetVSize();
|
||||
const HYPRE_BigInt *face_nbr_glob_lcol = trial_pfes->GetFaceNbrGlobalDofMap();
|
||||
const HYPRE_BigInt lcol_offset = trial_pfes->GetMyDofOffset();
|
||||
|
||||
Array<HYPRE_BigInt> glob_J(A_local->NumNonZeroElems());
|
||||
const int *J = A_local->GetJ();
|
||||
for (int i = 0; i < glob_J.Size(); i++)
|
||||
{
|
||||
if (J[i] < lvcols)
|
||||
{
|
||||
glob_J[i] = J[i] + lcol_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
glob_J[i] = face_nbr_glob_lcol[J[i] - lvcols];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - construct dA directly in the A format
|
||||
hdA.Reset(
|
||||
new HypreParMatrix(trial_pfes->GetComm(), lvrows, test_pfes->GlobalVSize(),
|
||||
trial_pfes->GlobalVSize(), A_local->GetI(), glob_J,
|
||||
A_local->GetData(), test_pfes->GetDofOffsets(),
|
||||
trial_pfes->GetDofOffsets()));
|
||||
// - hdA owns the new HypreParMatrix
|
||||
// - the above constructor copies all input arrays
|
||||
glob_J.DeleteAll();
|
||||
dA.ConvertFrom(hdA);
|
||||
}
|
||||
// construct the rectangular block-diagonal matrix dA
|
||||
OperatorHandle dA(A.Type());
|
||||
dA.MakeRectangularBlockDiag(trial_pfes->GetComm(),
|
||||
test_pfes->GlobalVSize(),
|
||||
trial_pfes->GlobalVSize(),
|
||||
test_pfes->GetDofOffsets(),
|
||||
trial_pfes->GetDofOffsets(),
|
||||
mat);
|
||||
|
||||
OperatorHandle P_test(A.Type()), P_trial(A.Type());
|
||||
|
||||
@@ -846,44 +670,6 @@ void ParMixedBilinearForm::TrueAddMult(const Vector &x, Vector &y,
|
||||
test_pfes->Dof_TrueDof_Matrix()->MultTranspose(a, Yaux, 1.0, y);
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::ParallelEliminateTrialEssentialBC(
|
||||
const Array<int> &bdr_attr_is_ess)
|
||||
{
|
||||
Array<int> trial_tdof_list;
|
||||
trial_pfes->GetEssentialTrueDofs(bdr_attr_is_ess, trial_tdof_list);
|
||||
|
||||
ParallelEliminateTrialTDofs(trial_tdof_list);
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::ParallelEliminateTrialTDofs(
|
||||
const Array<int> &trial_tdof_list)
|
||||
{
|
||||
HypreParMatrix *temp = p_mat.As<HypreParMatrix>()->EliminateCols(
|
||||
trial_tdof_list);
|
||||
p_mat_e.Reset(temp, true);
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::ParallelEliminateTrialTDofsInRHS(
|
||||
const Array<int> &trial_tdof_list, const Vector &x, Vector &b)
|
||||
{
|
||||
p_mat_e.As<HypreParMatrix>()->Mult(-1.0, x, 1.0, b);
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::ParallelEliminateTestEssentialBC(
|
||||
const Array<int> &bdr_attr_is_ess)
|
||||
{
|
||||
Array<int> test_tdof_list;
|
||||
test_pfes->GetEssentialTrueDofs(bdr_attr_is_ess, test_tdof_list);
|
||||
|
||||
ParallelEliminateTestTDofs(test_tdof_list);
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::ParallelEliminateTestTDofs(
|
||||
const Array<int> &test_tdof_list)
|
||||
{
|
||||
p_mat.As<HypreParMatrix>()->EliminateRows(test_tdof_list);
|
||||
}
|
||||
|
||||
void ParMixedBilinearForm::FormRectangularSystemMatrix(
|
||||
const Array<int>
|
||||
&trial_tdof_list,
|
||||
@@ -904,8 +690,10 @@ void ParMixedBilinearForm::FormRectangularSystemMatrix(
|
||||
mat = NULL;
|
||||
delete mat_e;
|
||||
mat_e = NULL;
|
||||
ParallelEliminateTrialTDofs(trial_tdof_list);
|
||||
ParallelEliminateTestTDofs(test_tdof_list);
|
||||
HypreParMatrix *temp =
|
||||
p_mat.As<HypreParMatrix>()->EliminateCols(trial_tdof_list);
|
||||
p_mat.As<HypreParMatrix>()->EliminateRows(test_tdof_list);
|
||||
p_mat_e.Reset(temp, true);
|
||||
}
|
||||
|
||||
A = p_mat;
|
||||
@@ -935,7 +723,7 @@ void ParMixedBilinearForm::FormRectangularLinearSystem(
|
||||
test_P->MultTranspose(b, B);
|
||||
trial_R->Mult(x, X);
|
||||
|
||||
ParallelEliminateTrialTDofsInRHS(trial_tdof_list, X, B);
|
||||
p_mat_e.As<HypreParMatrix>()->Mult(-1.0, X, 1.0, B);
|
||||
B.SetSubVector(test_tdof_list, 0.0);
|
||||
}
|
||||
|
||||
|
||||
+5
-128
@@ -73,7 +73,7 @@ public:
|
||||
/** When set to true and the ParBilinearForm has interior face integrators,
|
||||
the local SparseMatrix will include the rows (in addition to the columns)
|
||||
corresponding to face-neighbor dofs. The default behavior is to disregard
|
||||
those rows. Must be called before the first Assemble() call. */
|
||||
those rows. Must be called before the first Assemble call. */
|
||||
void KeepNbrBlock(bool knb = true) { keep_nbr_block = knb; }
|
||||
|
||||
/** @brief Set the operator type id for the parallel matrix/operator when
|
||||
@@ -101,14 +101,6 @@ public:
|
||||
diagonal for this case. */
|
||||
void AssembleDiagonal(Vector &diag) const override;
|
||||
|
||||
/// Returns the matrix assembled on the true dofs, i.e. P^t A P.
|
||||
/** The returned matrix is the internal one, owned by the form. It is not
|
||||
reassembled if it has been already constructed. If FormSystemMatrix()
|
||||
has been called before, it is the system matrix with eliminated
|
||||
essential DOFs, otherwise the parallel matrix is assembled here without
|
||||
the elimination process. */
|
||||
HypreParMatrix *ParallelAssembleInternalMatrix();
|
||||
|
||||
/// Returns the matrix assembled on the true dofs, i.e. P^t A P.
|
||||
/** The returned matrix has to be deleted by the caller. */
|
||||
HypreParMatrix *ParallelAssemble() { return ParallelAssemble(mat); }
|
||||
@@ -154,13 +146,6 @@ public:
|
||||
const HypreParVector &X,
|
||||
HypreParVector &B) const;
|
||||
|
||||
/// Eliminate essential boundary DOFs from the parallel system matrix.
|
||||
/** The array @a bdr_attr_is_ess marks boundary attributes that constitute
|
||||
the essential part of the boundary. */
|
||||
void ParallelEliminateEssentialBC(const Array<int> &bdr_attr_is_ess,
|
||||
const HypreParVector &X,
|
||||
HypreParVector &B);
|
||||
|
||||
/// Eliminate essential boundary DOFs from a parallel assembled matrix @a A.
|
||||
/** The array @a bdr_attr_is_ess marks boundary attributes that constitute
|
||||
the essential part of the boundary. The eliminated part is stored in a
|
||||
@@ -172,12 +157,6 @@ public:
|
||||
HypreParMatrix *ParallelEliminateEssentialBC(const Array<int> &bdr_attr_is_ess,
|
||||
HypreParMatrix &A) const;
|
||||
|
||||
/// Eliminate essential boundary DOFs from the parallel system matrix.
|
||||
/** The array @a bdr_attr_is_ess marks boundary attributes that constitute
|
||||
the essential part of the boundary. This method relies on
|
||||
ParallelEliminateTDofs(const Array<int> &), see it for details. */
|
||||
void ParallelEliminateEssentialBC(const Array<int> &bdr_attr_is_ess);
|
||||
|
||||
/// Eliminate essential true DOFs from a parallel assembled matrix @a A.
|
||||
/** Given a list of essential true dofs and the parallel assembled matrix
|
||||
@a A, eliminate the true dofs from the matrix, storing the eliminated
|
||||
@@ -190,28 +169,6 @@ public:
|
||||
HypreParMatrix &A) const
|
||||
{ return A.EliminateRowsCols(tdofs_list); }
|
||||
|
||||
/// Eliminate essential true DOFs from the parallel system matrix.
|
||||
/** Given a list of essential true dofs, eliminate the true dofs from
|
||||
the parallel assembled system matrix, storing the eliminated part
|
||||
internally. This method works in conjunction with
|
||||
ParallelEliminateTDofsInRHS() and allows elimination of boundary
|
||||
conditions in multiple right-hand sides. */
|
||||
void ParallelEliminateTDofs(const Array<int> &tdofs_list);
|
||||
|
||||
/** @brief Use the stored eliminated part of the parallel system matrix for
|
||||
elimination of boundary conditions in the r.h.s. */
|
||||
/** Given a list of essential true dofs, eliminate the true dofs from the
|
||||
right-hand side @a b using the solution vector @a x and the previously
|
||||
stored eliminated part of the parallel assembled system matrix produced
|
||||
by ParallelEliminateTDofs(const Array<int> &). */
|
||||
void ParallelEliminateTDofsInRHS(const Array<int> &tdofs, const Vector &x,
|
||||
Vector &b);
|
||||
|
||||
/// @deprecated Use ParallelEliminateTDofsInRHS() instead.
|
||||
MFEM_DEPRECATED void EliminateVDofsInRHS(const Array<int> &vdofs,
|
||||
const Vector &x, Vector &b)
|
||||
{ ParallelEliminateTDofsInRHS(vdofs, x, b); }
|
||||
|
||||
/** @brief Compute @a y += @a a (P^t A P) @a x, where @a x and @a y are
|
||||
vectors on the true dofs. */
|
||||
void TrueAddMult(const Vector &x, Vector &y, const real_t a = 1.0) const;
|
||||
@@ -281,6 +238,8 @@ public:
|
||||
|
||||
void Update(FiniteElementSpace *nfes = NULL) override;
|
||||
|
||||
void EliminateVDofsInRHS(const Array<int> &vdofs, const Vector &x, Vector &b);
|
||||
|
||||
virtual ~ParBilinearForm() { }
|
||||
};
|
||||
|
||||
@@ -298,13 +257,6 @@ protected:
|
||||
/// Matrix and eliminated matrix
|
||||
OperatorHandle p_mat, p_mat_e;
|
||||
|
||||
bool keep_nbr_block;
|
||||
|
||||
// Allocate mat - called when (mat == NULL && fbfi.Size() > 0)
|
||||
void pAllocMat();
|
||||
|
||||
void AssembleSharedFaces(int skip_zeros = 1);
|
||||
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
ParMixedBilinearForm(const ParMixedBilinearForm &);
|
||||
@@ -324,7 +276,6 @@ public:
|
||||
{
|
||||
trial_pfes = trial_fes;
|
||||
test_pfes = test_fes;
|
||||
keep_nbr_block = false;
|
||||
}
|
||||
|
||||
/** @brief Create a ParMixedBilinearForm on the given FiniteElementSpace%s
|
||||
@@ -344,89 +295,15 @@ public:
|
||||
{
|
||||
trial_pfes = trial_fes;
|
||||
test_pfes = test_fes;
|
||||
keep_nbr_block = false;
|
||||
}
|
||||
|
||||
/** When set to true and the ParMixedBilinearForm has interior face
|
||||
integrators, the local SparseMatrix will include the rows (in addition
|
||||
to the columns) corresponding to face-neighbor dofs. The default
|
||||
behavior is to disregard those rows. Must be called before the first
|
||||
Assemble() call. */
|
||||
void KeepNbrBlock(bool knb = true) { keep_nbr_block = knb; }
|
||||
|
||||
/// Assemble the local matrix
|
||||
void Assemble(int skip_zeros = 1);
|
||||
|
||||
/// Returns the matrix assembled on the true dofs, i.e. P_test^t A P_trial.
|
||||
/** The returned matrix is the internal one, owned by the form. It is not
|
||||
reassembled if it has been already constructed. If
|
||||
FormRectangularSystemMatrix() has been called before, it is the system
|
||||
matrix with eliminated essential DOFs, otherwise the parallel matrix is
|
||||
assembled here without the elimination process. */
|
||||
HypreParMatrix *ParallelAssembleInternalMatrix();
|
||||
|
||||
/// Returns the matrix assembled on the true dofs, i.e. P_test^t A P_trial.
|
||||
/** The returned matrix has to be deleted by the caller. */
|
||||
HypreParMatrix *ParallelAssemble() { return ParallelAssemble(mat); }
|
||||
|
||||
/** @brief Returns the eliminated matrix assembled on the true dofs, i.e.
|
||||
P_test^t A_local P_trial. */
|
||||
/** The returned matrix has to be deleted by the caller. */
|
||||
HypreParMatrix *ParallelAssembleElim() { return ParallelAssemble(mat_e); }
|
||||
|
||||
/** @brief Return the matrix @a m assembled on the true dofs, i.e. P_test^t
|
||||
A_local P_trial. */
|
||||
/** The returned matrix has to be deleted by the caller. */
|
||||
HypreParMatrix *ParallelAssemble(SparseMatrix *m);
|
||||
HypreParMatrix *ParallelAssemble();
|
||||
|
||||
/** @brief Returns the matrix assembled on the true dofs, i.e.
|
||||
@a A = P_test^t A_local P_trial, in the format (type id) specified by
|
||||
@a A. */
|
||||
void ParallelAssemble(OperatorHandle &A) { ParallelAssemble(A, mat); }
|
||||
|
||||
/** Returns the eliminated matrix assembled on the true dofs, i.e.
|
||||
@a A_elim = P^t A_elim_local P in the format (type id) specified by @a A.
|
||||
*/
|
||||
void ParallelAssembleElim(OperatorHandle &A_elim)
|
||||
{ ParallelAssemble(A_elim, mat_e); }
|
||||
|
||||
/** Returns the matrix @a A_local assembled on the true dofs, i.e.
|
||||
@a A = P_test^t A_local P_trial in the format (type id) specified by
|
||||
@a A. */
|
||||
void ParallelAssemble(OperatorHandle &A, SparseMatrix *A_local);
|
||||
|
||||
/// Eliminate essential boundary trial DOFs from the parallel system matrix.
|
||||
/** The array @a bdr_attr_is_ess marks boundary attributes that constitute
|
||||
the essential part of the boundary. This method relies on
|
||||
ParallelEliminateTrialTDofs(const Array<int> &), see it for details. */
|
||||
void ParallelEliminateTrialEssentialBC(const Array<int> &bdr_attr_is_ess);
|
||||
|
||||
/// Eliminate essential trial true DOFs from the parallel system matrix.
|
||||
/** Given a list of essential trial true dofs, eliminate the trial true dofs
|
||||
from the parallel assembled system matrix, storing the eliminated part
|
||||
internally. This method works in conjunction with
|
||||
ParallelEliminateTrialTDofsInRHS() and allows elimination of boundary
|
||||
conditions in multiple right-hand sides. */
|
||||
void ParallelEliminateTrialTDofs(const Array<int> &trial_tdof_list);
|
||||
|
||||
/** @brief Use the stored eliminated part of the parallel system matrix for
|
||||
elimination of boundary conditions in the r.h.s. */
|
||||
/** Given a list of essential trial true dofs, eliminate the trial true dofs
|
||||
from the right-hand side @a B using the solution vector @a X and the
|
||||
previously stored eliminated part of the parallel assembled system
|
||||
matrix produced by ParallelEliminateTrialTDofs(const Array<int> &). */
|
||||
void ParallelEliminateTrialTDofsInRHS(const Array<int> &trial_tdof_list,
|
||||
const Vector &X, Vector &B);
|
||||
|
||||
/// Eliminate essential boundary test DOFs from the parallel system matrix.
|
||||
/** The array @a bdr_attr_is_ess marks boundary attributes that constitute
|
||||
the essential part of the boundary. */
|
||||
void ParallelEliminateTestEssentialBC(const Array<int> &bdr_attr_is_ess);
|
||||
|
||||
/// Eliminate essential test true DOFs from the parallel system matrix.
|
||||
/** Given a list of essential test true dofs, eliminate the test true dofs
|
||||
from the parallel assembled system matrix. */
|
||||
void ParallelEliminateTestTDofs(const Array<int> &test_tdof_list);
|
||||
void ParallelAssemble(OperatorHandle &A);
|
||||
|
||||
using MixedBilinearForm::FormRectangularSystemMatrix;
|
||||
using MixedBilinearForm::FormRectangularLinearSystem;
|
||||
|
||||
+43
-407
@@ -105,59 +105,6 @@ const SparseMatrix &ParNonlinearForm::GetLocalGradient(const Vector &x) const
|
||||
return *Grad;
|
||||
}
|
||||
|
||||
void ParNonlinearForm::GradientSharedFaces(const Vector &x,
|
||||
int skip_zeros) const
|
||||
{
|
||||
ParFiniteElementSpace *pfes = ParFESpace();
|
||||
ParMesh *pmesh = pfes->GetParMesh();
|
||||
FaceElementTransformations *T;
|
||||
Array<int> vdofs1, vdofs2, vdofs_all;
|
||||
DenseMatrix elemmat;
|
||||
Vector el_x, nbr_x, face_x;
|
||||
const Vector &px = Prolongate(x);
|
||||
|
||||
ParGridFunction pgf(pfes, const_cast<Vector&>(px), 0);
|
||||
pgf.ExchangeFaceNbrData();
|
||||
|
||||
int nfaces = pmesh->GetNSharedFaces();
|
||||
for (int i = 0; i < nfaces; i++)
|
||||
{
|
||||
T = pmesh->GetSharedFaceTransformations(i);
|
||||
int Elem2NbrNo = T->Elem2No - pmesh->GetNE();
|
||||
|
||||
pfes->GetElementVDofs(T->Elem1No, vdofs1);
|
||||
pfes->GetFaceNbrElementVDofs(Elem2NbrNo, vdofs2);
|
||||
face_x.SetSize(vdofs1.Size() + vdofs2.Size());
|
||||
|
||||
el_x.MakeRef(face_x, 0, vdofs1.Size());
|
||||
pgf.GetSubVector(vdofs1, el_x);
|
||||
|
||||
nbr_x.MakeRef(face_x, vdofs1.Size(), vdofs2.Size());
|
||||
pgf.FaceNbrData().GetSubVector(vdofs2, nbr_x);
|
||||
|
||||
vdofs1.Copy(vdofs_all);
|
||||
for (int j = 0; j < vdofs2.Size(); j++)
|
||||
{
|
||||
if (vdofs2[j] >= 0)
|
||||
{
|
||||
vdofs2[j] += height;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdofs2[j] -= height;
|
||||
}
|
||||
}
|
||||
vdofs_all.Append(vdofs2);
|
||||
for (int k = 0; k < fnfi.Size(); k++)
|
||||
{
|
||||
fnfi[k]->AssembleFaceGrad(*pfes->GetFE(T->Elem1No),
|
||||
*pfes->GetFaceNbrFE(Elem2NbrNo),
|
||||
*T, face_x, elemmat);
|
||||
Grad->AddSubMatrix(vdofs1, vdofs_all, elemmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Operator &ParNonlinearForm::GetGradient(const Vector &x) const
|
||||
{
|
||||
if (NonlinearForm::ext) { return NonlinearForm::GetGradient(x); }
|
||||
@@ -165,61 +112,19 @@ Operator &ParNonlinearForm::GetGradient(const Vector &x) const
|
||||
ParFiniteElementSpace *pfes = ParFESpace();
|
||||
|
||||
pGrad.Clear();
|
||||
OperatorHandle dA(pGrad.Type()), Ph(pGrad.Type()), hdA;
|
||||
|
||||
if (fnfi.Size())
|
||||
NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.
|
||||
|
||||
OperatorHandle dA(pGrad.Type()), Ph(pGrad.Type());
|
||||
|
||||
if (fnfi.Size() == 0)
|
||||
{
|
||||
const int skip_zeros = 0;
|
||||
|
||||
pfes->ExchangeFaceNbrData();
|
||||
if (Grad == NULL)
|
||||
{
|
||||
int nbr_size = pfes->GetFaceNbrVSize();
|
||||
Grad = new SparseMatrix(pfes->GetVSize(), pfes->GetVSize() + nbr_size);
|
||||
}
|
||||
|
||||
NonlinearForm::GetGradient(x, false); // (re)assemble Grad, no b.c.
|
||||
|
||||
GradientSharedFaces(x, skip_zeros);
|
||||
|
||||
Grad->Finalize(skip_zeros);
|
||||
|
||||
// handle the case when 'a' contains off-diagonal
|
||||
int lvsize = pfes->GetVSize();
|
||||
const HYPRE_BigInt *face_nbr_glob_ldof = pfes->GetFaceNbrGlobalDofMap();
|
||||
HYPRE_BigInt ldof_offset = pfes->GetMyDofOffset();
|
||||
|
||||
Array<HYPRE_BigInt> glob_J(Grad->NumNonZeroElems());
|
||||
int *J = Grad->GetJ();
|
||||
for (int i = 0; i < glob_J.Size(); i++)
|
||||
{
|
||||
if (J[i] < lvsize)
|
||||
{
|
||||
glob_J[i] = J[i] + ldof_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
glob_J[i] = face_nbr_glob_ldof[J[i] - lvsize];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - construct dA directly in the A format
|
||||
hdA.Reset(
|
||||
new HypreParMatrix(pfes->GetComm(), lvsize, pfes->GlobalVSize(),
|
||||
pfes->GlobalVSize(), Grad->GetI(), glob_J,
|
||||
Grad->GetData(), pfes->GetDofOffsets(),
|
||||
pfes->GetDofOffsets()));
|
||||
// - hdA owns the new HypreParMatrix
|
||||
// - the above constructor copies all input arrays
|
||||
glob_J.DeleteAll();
|
||||
dA.ConvertFrom(hdA);
|
||||
dA.MakeSquareBlockDiag(pfes->GetComm(), pfes->GlobalVSize(),
|
||||
pfes->GetDofOffsets(), Grad);
|
||||
}
|
||||
else
|
||||
{
|
||||
NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.
|
||||
|
||||
dA.MakeSquareBlockDiag(pfes->GetComm(), pfes->GlobalVSize(),
|
||||
pfes->GetDofOffsets(), Grad);
|
||||
MFEM_ABORT("TODO: assemble contributions from shared face terms");
|
||||
}
|
||||
|
||||
// RAP the local gradient dA.
|
||||
@@ -366,70 +271,7 @@ void ParBlockNonlinearForm::Mult(const Vector &x, Vector &y) const
|
||||
|
||||
if (fnfi.Size() > 0)
|
||||
{
|
||||
// Terms over shared interior faces in parallel.
|
||||
ParMesh *pmesh = ParFESpace(0)->GetParMesh();
|
||||
FaceElementTransformations *tr;
|
||||
|
||||
Array<Array<int> *>vdofs(fes.Size());
|
||||
Array<Array<int> *>vdofs2(fes.Size());
|
||||
Array<Vector *> el_x(fes.Size());
|
||||
Array<const Vector *> el_x_const(fes.Size());
|
||||
Array<Vector *> el_y(fes.Size());
|
||||
Array<const FiniteElement *> fe(fes.Size());
|
||||
Array<const FiniteElement *> fe2(fes.Size());
|
||||
Array<ParGridFunction *> pgfs(fes.Size());
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
{
|
||||
el_x_const[s] = el_x[s] = new Vector();
|
||||
el_y[s] = new Vector();
|
||||
vdofs[s] = new Array<int>;
|
||||
vdofs2[s] = new Array<int>;
|
||||
pgfs[s] = new ParGridFunction(const_cast<ParFiniteElementSpace*>(ParFESpace(s)),
|
||||
xs.GetBlock(s));
|
||||
pgfs[s]->ExchangeFaceNbrData();
|
||||
}
|
||||
|
||||
const int n_shared_faces = pmesh->GetNSharedFaces();
|
||||
for (int i = 0; i < n_shared_faces; i++)
|
||||
{
|
||||
tr = pmesh->GetSharedFaceTransformations(i, true);
|
||||
int Elem2NbrNo = tr->Elem2No - pmesh->GetNE();
|
||||
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
{
|
||||
const ParFiniteElementSpace *pfes = ParFESpace(s);
|
||||
fe[s] = pfes->GetFE(tr->Elem1No);
|
||||
fe2[s] = pfes->GetFaceNbrFE(Elem2NbrNo);
|
||||
|
||||
pfes->GetElementVDofs(tr->Elem1No, *(vdofs[s]));
|
||||
pfes->GetFaceNbrElementVDofs(Elem2NbrNo, *(vdofs2[s]));
|
||||
|
||||
el_x[s]->SetSize(vdofs[s]->Size() + vdofs2[s]->Size());
|
||||
xs.GetBlock(s).GetSubVector(*(vdofs[s]), el_x[s]->GetData());
|
||||
pgfs[s]->FaceNbrData().GetSubVector(*(vdofs2[s]),
|
||||
el_x[s]->GetData() + vdofs[s]->Size());
|
||||
}
|
||||
|
||||
for (int k = 0; k < fnfi.Size(); ++k)
|
||||
{
|
||||
fnfi[k]->AssembleFaceVector(fe, fe2, *tr, el_x_const, el_y);
|
||||
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
{
|
||||
if (el_y[s]->Size() == 0) { continue; }
|
||||
ys.GetBlock(s).AddElementVector(*(vdofs[s]), *el_y[s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
{
|
||||
delete pgfs[s];
|
||||
delete vdofs2[s];
|
||||
delete vdofs[s];
|
||||
delete el_y[s];
|
||||
delete el_x[s];
|
||||
}
|
||||
MFEM_ABORT("TODO: assemble contributions from shared face terms");
|
||||
}
|
||||
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
@@ -486,106 +328,6 @@ void ParBlockNonlinearForm::SetGradientType(Operator::Type tid)
|
||||
}
|
||||
}
|
||||
|
||||
void ParBlockNonlinearForm::GradientSharedFaces(const BlockVector &xs,
|
||||
int skip_zeros) const
|
||||
{
|
||||
// Terms over shared interior faces in parallel.
|
||||
ParMesh *pmesh = ParFESpace(0)->GetParMesh();
|
||||
FaceElementTransformations *tr;
|
||||
|
||||
Array<Array<int> *>vdofs(fes.Size());
|
||||
Array<Array<int> *>vdofs2(fes.Size());
|
||||
Array<Array<int> *>vdofs_all(fes.Size());
|
||||
Array<Vector *> el_x(fes.Size());
|
||||
Array<const Vector *> el_x_const(fes.Size());
|
||||
Array2D<DenseMatrix *> elmats(fes.Size(), fes.Size());
|
||||
Array<const FiniteElement *> fe(fes.Size());
|
||||
Array<const FiniteElement *> fe2(fes.Size());
|
||||
Array<ParGridFunction *> pgfs(fes.Size());
|
||||
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
{
|
||||
el_x_const[s1] = el_x[s1] = new Vector();
|
||||
vdofs[s1] = new Array<int>;
|
||||
vdofs2[s1] = new Array<int>;
|
||||
vdofs_all[s1] = new Array<int>;
|
||||
pgfs[s1] = new ParGridFunction(
|
||||
const_cast<ParFiniteElementSpace*>(ParFESpace(s1)),
|
||||
const_cast<Vector&>(xs.GetBlock(s1)));
|
||||
pgfs[s1]->ExchangeFaceNbrData();
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
{
|
||||
elmats(s1,s2) = new DenseMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
const int n_shared_faces = pmesh->GetNSharedFaces();
|
||||
for (int i = 0; i < n_shared_faces; i++)
|
||||
{
|
||||
tr = pmesh->GetSharedFaceTransformations(i, true);
|
||||
int Elem2NbrNo = tr->Elem2No - pmesh->GetNE();
|
||||
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
{
|
||||
const ParFiniteElementSpace *pfes = ParFESpace(s);
|
||||
fe[s] = pfes->GetFE(tr->Elem1No);
|
||||
fe2[s] = pfes->GetFaceNbrFE(Elem2NbrNo);
|
||||
|
||||
pfes->GetElementVDofs(tr->Elem1No, *(vdofs[s]));
|
||||
pfes->GetFaceNbrElementVDofs(Elem2NbrNo, *(vdofs2[s]));
|
||||
|
||||
el_x[s]->SetSize(vdofs[s]->Size() + vdofs2[s]->Size());
|
||||
xs.GetBlock(s).GetSubVector(*(vdofs[s]), el_x[s]->GetData());
|
||||
pgfs[s]->FaceNbrData().GetSubVector(*(vdofs2[s]),
|
||||
el_x[s]->GetData() + vdofs[s]->Size());
|
||||
|
||||
vdofs[s]->Copy(*vdofs_all[s]);
|
||||
|
||||
const int lvsize = pfes->GetVSize();
|
||||
for (int j = 0; j < vdofs2[s]->Size(); j++)
|
||||
{
|
||||
if ((*vdofs2[s])[j] >= 0)
|
||||
{
|
||||
(*vdofs2[s])[j] += lvsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*vdofs2[s])[j] -= lvsize;
|
||||
}
|
||||
}
|
||||
vdofs_all[s]->Append(*(vdofs2[s]));
|
||||
}
|
||||
|
||||
for (int k = 0; k < fnfi.Size(); ++k)
|
||||
{
|
||||
fnfi[k]->AssembleFaceGrad(fe, fe2, *tr, el_x_const, elmats);
|
||||
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
{
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
{
|
||||
if (elmats(s1,s2)->Height() == 0) { continue; }
|
||||
Grads(s1,s2)->AddSubMatrix(*vdofs[s1], *vdofs_all[s2],
|
||||
*elmats(s1,s2), skip_zeros);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
{
|
||||
delete pgfs[s1];
|
||||
delete vdofs_all[s1];
|
||||
delete vdofs2[s1];
|
||||
delete vdofs[s1];
|
||||
delete el_x[s1];
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
{
|
||||
delete elmats(s1,s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockOperator & ParBlockNonlinearForm::GetGradient(const Vector &x) const
|
||||
{
|
||||
if (pBlockGrad == NULL)
|
||||
@@ -605,155 +347,49 @@ BlockOperator & ParBlockNonlinearForm::GetGradient(const Vector &x) const
|
||||
}
|
||||
}
|
||||
|
||||
// xs_true is not modified, so const_cast is okay
|
||||
xs_true.Update(const_cast<Vector &>(x), block_trueOffsets);
|
||||
xs.Update(block_offsets);
|
||||
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
{
|
||||
fes[s]->GetProlongationMatrix()->Mult(
|
||||
xs_true.GetBlock(s), xs.GetBlock(s));
|
||||
}
|
||||
GetLocalGradient(x); // gradients are stored in 'Grads'
|
||||
|
||||
if (fnfi.Size() > 0)
|
||||
{
|
||||
const int skip_zeros = 0;
|
||||
|
||||
for (int s=0; s<fes.Size(); ++s)
|
||||
{
|
||||
const_cast<ParFiniteElementSpace*>(pfes[s])->ExchangeFaceNbrData();
|
||||
}
|
||||
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
{
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
{
|
||||
if (Grads(s1,s2) == NULL)
|
||||
{
|
||||
int nbr_size = pfes[s2]->GetFaceNbrVSize();
|
||||
Grads(s1,s2) = new SparseMatrix(pfes[s1]->GetVSize(),
|
||||
pfes[s2]->GetVSize() + nbr_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// (re)assemble Grad without b.c. into 'Grads'
|
||||
BlockNonlinearForm::ComputeGradientBlocked(xs, false);
|
||||
|
||||
GradientSharedFaces(xs, skip_zeros);
|
||||
|
||||
// finalize the gradients
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
{
|
||||
Grads(s1,s2)->Finalize(skip_zeros);
|
||||
}
|
||||
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
{
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
{
|
||||
OperatorHandle hdA;
|
||||
OperatorHandle dA(phBlockGrad(s1,s2)->Type()),
|
||||
Ph(phBlockGrad(s1,s2)->Type()),
|
||||
Rh(phBlockGrad(s1,s2)->Type());
|
||||
|
||||
// handle the case when 'a' contains off-diagonal
|
||||
int lvsize = pfes[s2]->GetVSize();
|
||||
const HYPRE_BigInt *face_nbr_glob_ldof =
|
||||
const_cast<ParFiniteElementSpace*>(pfes[s2])->GetFaceNbrGlobalDofMap();
|
||||
HYPRE_BigInt ldof_offset = pfes[s2]->GetMyDofOffset();
|
||||
|
||||
Array<HYPRE_BigInt> glob_J(Grads(s1,s2)->NumNonZeroElems());
|
||||
int *J = Grads(s1,s2)->GetJ();
|
||||
for (int i = 0; i < glob_J.Size(); i++)
|
||||
{
|
||||
if (J[i] < lvsize)
|
||||
{
|
||||
glob_J[i] = J[i] + ldof_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
glob_J[i] = face_nbr_glob_ldof[J[i] - lvsize];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - construct dA directly in the A format
|
||||
hdA.Reset(
|
||||
new HypreParMatrix(pfes[s2]->GetComm(), pfes[s1]->GetVSize(),
|
||||
pfes[s1]->GlobalVSize(), pfes[s2]->GlobalVSize(),
|
||||
Grads(s1,s2)->GetI(), glob_J, Grads(s1,s2)->GetData(),
|
||||
pfes[s1]->GetDofOffsets(), pfes[s2]->GetDofOffsets()));
|
||||
// - hdA owns the new HypreParMatrix
|
||||
// - the above constructor copies all input arrays
|
||||
glob_J.DeleteAll();
|
||||
dA.ConvertFrom(hdA);
|
||||
|
||||
if (s1 == s2)
|
||||
{
|
||||
Ph.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
|
||||
phBlockGrad(s1,s1)->MakePtAP(dA, Ph);
|
||||
|
||||
OperatorHandle Ae;
|
||||
Ae.EliminateRowsCols(*phBlockGrad(s1,s1), *ess_tdofs[s1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rh.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
|
||||
Ph.ConvertFrom(pfes[s2]->Dof_TrueDof_Matrix());
|
||||
|
||||
phBlockGrad(s1,s2)->MakeRAP(Rh, dA, Ph);
|
||||
|
||||
phBlockGrad(s1,s2)->EliminateRows(*ess_tdofs[s1]);
|
||||
phBlockGrad(s1,s2)->EliminateCols(*ess_tdofs[s2]);
|
||||
}
|
||||
|
||||
pBlockGrad->SetBlock(s1, s2, phBlockGrad(s1,s2)->Ptr());
|
||||
}
|
||||
}
|
||||
MFEM_ABORT("TODO: assemble contributions from shared face terms");
|
||||
}
|
||||
else
|
||||
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
{
|
||||
// (re)assemble Grad without b.c. into 'Grads'
|
||||
BlockNonlinearForm::ComputeGradientBlocked(xs);
|
||||
|
||||
for (int s1=0; s1<fes.Size(); ++s1)
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
{
|
||||
for (int s2=0; s2<fes.Size(); ++s2)
|
||||
OperatorHandle dA(phBlockGrad(s1,s2)->Type()),
|
||||
Ph(phBlockGrad(s1,s2)->Type()),
|
||||
Rh(phBlockGrad(s1,s2)->Type());
|
||||
|
||||
if (s1 == s2)
|
||||
{
|
||||
OperatorHandle dA(phBlockGrad(s1,s2)->Type()),
|
||||
Ph(phBlockGrad(s1,s2)->Type()),
|
||||
Rh(phBlockGrad(s1,s2)->Type());
|
||||
dA.MakeSquareBlockDiag(pfes[s1]->GetComm(), pfes[s1]->GlobalVSize(),
|
||||
pfes[s1]->GetDofOffsets(), Grads(s1,s1));
|
||||
Ph.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
|
||||
phBlockGrad(s1,s1)->MakePtAP(dA, Ph);
|
||||
|
||||
if (s1 == s2)
|
||||
{
|
||||
dA.MakeSquareBlockDiag(pfes[s1]->GetComm(), pfes[s1]->GlobalVSize(),
|
||||
pfes[s1]->GetDofOffsets(), Grads(s1,s1));
|
||||
Ph.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
|
||||
phBlockGrad(s1,s1)->MakePtAP(dA, Ph);
|
||||
|
||||
OperatorHandle Ae;
|
||||
Ae.EliminateRowsCols(*phBlockGrad(s1,s1), *ess_tdofs[s1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dA.MakeRectangularBlockDiag(pfes[s1]->GetComm(),
|
||||
pfes[s1]->GlobalVSize(),
|
||||
pfes[s2]->GlobalVSize(),
|
||||
pfes[s1]->GetDofOffsets(),
|
||||
pfes[s2]->GetDofOffsets(),
|
||||
Grads(s1,s2));
|
||||
Rh.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
|
||||
Ph.ConvertFrom(pfes[s2]->Dof_TrueDof_Matrix());
|
||||
|
||||
phBlockGrad(s1,s2)->MakeRAP(Rh, dA, Ph);
|
||||
|
||||
phBlockGrad(s1,s2)->EliminateRows(*ess_tdofs[s1]);
|
||||
phBlockGrad(s1,s2)->EliminateCols(*ess_tdofs[s2]);
|
||||
}
|
||||
|
||||
pBlockGrad->SetBlock(s1, s2, phBlockGrad(s1,s2)->Ptr());
|
||||
OperatorHandle Ae;
|
||||
Ae.EliminateRowsCols(*phBlockGrad(s1,s1), *ess_tdofs[s1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dA.MakeRectangularBlockDiag(pfes[s1]->GetComm(),
|
||||
pfes[s1]->GlobalVSize(),
|
||||
pfes[s2]->GlobalVSize(),
|
||||
pfes[s1]->GetDofOffsets(),
|
||||
pfes[s2]->GetDofOffsets(),
|
||||
Grads(s1,s2));
|
||||
Rh.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
|
||||
Ph.ConvertFrom(pfes[s2]->Dof_TrueDof_Matrix());
|
||||
|
||||
phBlockGrad(s1,s2)->MakeRAP(Rh, dA, Ph);
|
||||
|
||||
phBlockGrad(s1,s2)->EliminateRows(*ess_tdofs[s1]);
|
||||
phBlockGrad(s1,s2)->EliminateCols(*ess_tdofs[s2]);
|
||||
}
|
||||
|
||||
pBlockGrad->SetBlock(s1, s2, phBlockGrad(s1,s2)->Ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ protected:
|
||||
mutable ParGridFunction X, Y;
|
||||
mutable OperatorHandle pGrad;
|
||||
|
||||
void GradientSharedFaces(const Vector &x, int skip_zeros = 1) const;
|
||||
|
||||
public:
|
||||
ParNonlinearForm(ParFiniteElementSpace *pf);
|
||||
|
||||
@@ -83,8 +81,6 @@ protected:
|
||||
mutable Array2D<OperatorHandle *> phBlockGrad;
|
||||
mutable BlockOperator *pBlockGrad;
|
||||
|
||||
void GradientSharedFaces(const BlockVector &xs, int skip_zeros) const;
|
||||
|
||||
public:
|
||||
/// Computes the energy of the system
|
||||
real_t GetEnergy(const Vector &x) const override;
|
||||
|
||||
+9
-11
@@ -561,8 +561,7 @@ void CopyMemory(Memory<T> &src, Memory<T> &dst, MemoryClass dst_mc,
|
||||
this function. In particular, @a dst should be empty or deleted before
|
||||
calling this function. */
|
||||
template <typename SrcT, typename DstT>
|
||||
void CopyConvertMemory(const Memory<SrcT> &src, MemoryClass dst_mc,
|
||||
Memory<DstT> &dst)
|
||||
void CopyConvertMemory(Memory<SrcT> &src, MemoryClass dst_mc, Memory<DstT> &dst)
|
||||
{
|
||||
auto capacity = src.Capacity();
|
||||
dst.New(capacity, GetMemoryType(dst_mc));
|
||||
@@ -843,8 +842,8 @@ static int GetPartitioningArraySize(MPI_Comm comm)
|
||||
///
|
||||
/// Both @a row and @a col are partitioning arrays, whose length is returned by
|
||||
/// GetPartitioningArraySize(), see @ref hypre_partitioning_descr.
|
||||
static bool RowAndColStartsAreEqual(MPI_Comm comm, const HYPRE_BigInt *rows,
|
||||
const HYPRE_BigInt *cols)
|
||||
static bool RowAndColStartsAreEqual(MPI_Comm comm, HYPRE_BigInt *rows,
|
||||
HYPRE_BigInt *cols)
|
||||
{
|
||||
const int part_size = GetPartitioningArraySize(comm);
|
||||
bool are_equal = true;
|
||||
@@ -1132,7 +1131,7 @@ HypreParMatrix::HypreParMatrix(
|
||||
HypreParMatrix::HypreParMatrix(MPI_Comm comm,
|
||||
HYPRE_BigInt *row_starts,
|
||||
HYPRE_BigInt *col_starts,
|
||||
const SparseMatrix *sm_a)
|
||||
SparseMatrix *sm_a)
|
||||
{
|
||||
MFEM_ASSERT(sm_a != NULL, "invalid input");
|
||||
MFEM_VERIFY(!HYPRE_AssumedPartitionCheck(),
|
||||
@@ -1146,7 +1145,7 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm,
|
||||
|
||||
hypre_CSRMatrixSetDataOwner(csr_a,0);
|
||||
MemoryIJData mem_a;
|
||||
CopyCSR(const_cast<SparseMatrix*>(sm_a), mem_a, csr_a, false);
|
||||
CopyCSR(sm_a, mem_a, csr_a, false);
|
||||
hypre_CSRMatrixSetRownnz(csr_a);
|
||||
|
||||
// NOTE: this call creates a matrix on host even when device support is
|
||||
@@ -1308,11 +1307,10 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm, int id, int np,
|
||||
HypreParMatrix::HypreParMatrix(MPI_Comm comm, int nrows,
|
||||
HYPRE_BigInt glob_nrows,
|
||||
HYPRE_BigInt glob_ncols,
|
||||
const int *I,
|
||||
const HYPRE_BigInt *J,
|
||||
const real_t *data,
|
||||
const HYPRE_BigInt *rows,
|
||||
const HYPRE_BigInt *cols)
|
||||
int *I, HYPRE_BigInt *J,
|
||||
real_t *data,
|
||||
HYPRE_BigInt *rows,
|
||||
HYPRE_BigInt *cols)
|
||||
{
|
||||
Init();
|
||||
|
||||
|
||||
+4
-4
@@ -565,7 +565,7 @@ public:
|
||||
partitioning arrays @a row_starts and @a col_starts. */
|
||||
HypreParMatrix(MPI_Comm comm, HYPRE_BigInt *row_starts,
|
||||
HYPRE_BigInt *col_starts,
|
||||
const SparseMatrix *a); // constructor with 4 arguments, v2
|
||||
SparseMatrix *a); // constructor with 4 arguments, v2
|
||||
|
||||
/// Creates boolean block-diagonal rectangular parallel matrix.
|
||||
/** The new HypreParMatrix does not take ownership of any of the input
|
||||
@@ -594,9 +594,9 @@ public:
|
||||
arrays (so they can be deleted). See @ref hypre_partitioning_descr "here"
|
||||
for a description of the partitioning arrays @a rows and @a cols. */
|
||||
HypreParMatrix(MPI_Comm comm, int nrows, HYPRE_BigInt glob_nrows,
|
||||
HYPRE_BigInt glob_ncols, const int *I, const HYPRE_BigInt *J,
|
||||
const real_t *data, const HYPRE_BigInt *rows,
|
||||
const HYPRE_BigInt *cols); // constructor with 9 arguments
|
||||
HYPRE_BigInt glob_ncols, int *I, HYPRE_BigInt *J,
|
||||
real_t *data, HYPRE_BigInt *rows,
|
||||
HYPRE_BigInt *cols); // constructor with 9 arguments
|
||||
|
||||
/** @brief Copy constructor for a ParCSR matrix which creates a deep copy of
|
||||
structure and data from @a P. */
|
||||
|
||||
+1
-1
@@ -1014,7 +1014,7 @@ void NCNURBSExtension::GetMasterFaceDofs(bool dof, int mf,
|
||||
std::array<int, 4> orderedVertices;
|
||||
std::array<bool, 4> edgeBdry;
|
||||
std::set<int> vbdry;
|
||||
int nf1 = 0, nf2 = 0;
|
||||
int nf1, nf2;
|
||||
auto SetEdgeEntries = [&](int eidx, int edge, const Array<int> &evert,
|
||||
int &vstart)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,7 @@ ifneq (clean,$(MAKECMDGOALS))
|
||||
override shared = $(if $(MFEM_SHARED:YES=),,YES)
|
||||
endif
|
||||
|
||||
SEQ_MINIOBJS = mesh_extras.o fem_extras.o bravais.o
|
||||
SEQ_MINIOBJS = mesh_extras.o fem_extras.o
|
||||
ifeq ($(MFEM_USE_MPI),NO)
|
||||
MINIOBJS = $(SEQ_MINIOBJS)
|
||||
else
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at the
|
||||
# Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights reserved.
|
||||
# See file COPYRIGHT for details.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability see http://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Use the MFEM build directory
|
||||
MFEM_DIR ?= ../..
|
||||
MFEM_BUILD_DIR ?= ../..
|
||||
SRC = $(if $(MFEM_DIR:../..=),$(MFEM_DIR)/miniapps/meta-material/,)
|
||||
CONFIG_MK = $(MFEM_BUILD_DIR)/config/config.mk
|
||||
# Use the MFEM install directory
|
||||
# MFEM_INSTALL_DIR = ../../mfem
|
||||
# CONFIG_MK = $(MFEM_INSTALL_DIR)/share/mfem/config.mk
|
||||
|
||||
MFEM_LIB_FILE = mfem_is_not_built
|
||||
-include $(CONFIG_MK)
|
||||
|
||||
SEQ_MINIAPPS =
|
||||
PAR_MINIAPPS = meta_material
|
||||
ifeq ($(MFEM_USE_MPI),NO)
|
||||
MINIAPPS = $(SEQ_MINIAPPS)
|
||||
else
|
||||
MINIAPPS = $(PAR_MINIAPPS) $(SEQ_MINIAPPS)
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .o .cpp .mk
|
||||
.PHONY: all clean clean-build clean-exec
|
||||
|
||||
COMMON_O=../common/bravais.o ../common/pfem_extras.o
|
||||
|
||||
# Remove built-in rule
|
||||
%: %.cpp
|
||||
|
||||
# Replace the default implicit rule for *.cpp files
|
||||
%: $(SRC)%.cpp $(MFEM_LIB_FILE) $(CONFIG_MK) $(COMMON_O)
|
||||
$(MFEM_CXX) $(MFEM_FLAGS) $< -o $@ \
|
||||
$(COMMON_O) $(MFEM_LIBS)
|
||||
|
||||
all: $(MINIAPPS)
|
||||
|
||||
# Rules for building the miniapps
|
||||
$(MINIAPPS): \
|
||||
%: $(SRC)%.cpp %_solver.o $(COMMON_O) $(MFEM_LIB_FILE) $(CONFIG_MK)
|
||||
$(MFEM_CXX) $(MFEM_FLAGS) $< -o $@ $@_solver.o $(COMMON_O) $(MFEM_LIBS)
|
||||
|
||||
# Rules for compiling miniapp dependencies
|
||||
$(COMMON_O) $(addsuffix _solver.o,$(MINIAPPS)): \
|
||||
%.o: $(SRC)%.cpp $(SRC)%.hpp $(CONFIG_MK)
|
||||
$(MFEM_CXX) $(MFEM_FLAGS) -c $(<) -o $(@)
|
||||
|
||||
MFEM_TESTS = MINIAPPS
|
||||
include $(MFEM_TEST_MK)
|
||||
|
||||
# Testing: Parallel vs. serial runs
|
||||
RUN_MPI = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP) 4
|
||||
volta-test-par: meta_material
|
||||
@$(call mfem-test,$<, $(RUN_MPI), Meta-Material miniapp,\
|
||||
-bl 1 -rs 0 -rp 0)
|
||||
|
||||
# Testing: "test" target and mfem-test* variables are defined in config/test.mk
|
||||
|
||||
# Generate an error message if the MFEM library is not built and exit
|
||||
$(MFEM_LIB_FILE):
|
||||
$(error The MFEM library is not built)
|
||||
|
||||
clean: clean-build clean-exec
|
||||
|
||||
clean-build:
|
||||
rm -f *.o *~ test_meta_mat meta_material
|
||||
rm -rf *.dSYM *.TVD.*breakpoints
|
||||
|
||||
clean-exec:
|
||||
@rm -f mobius-strip.mesh klein-bottle.mesh mesh-explorer.mesh
|
||||
@rm -f partitioning.txt shaper.mesh
|
||||
@@ -1,692 +0,0 @@
|
||||
#include "mfem.hpp"
|
||||
#include "../common/bravais.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cerrno> // errno
|
||||
|
||||
#include "meta_material_solver.hpp"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/stat.h> // mkdir
|
||||
#else
|
||||
#include <direct.h> // _mkdir
|
||||
#define mkdir(dir, mode) _mkdir(dir)
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
using namespace mfem::miniapps;
|
||||
using namespace mfem::bravais;
|
||||
|
||||
// Volume Fraction Coefficient
|
||||
static int prob_ = -1;
|
||||
double vol_frac_coef(const Vector &);
|
||||
|
||||
int CreateDirectory(const string &dir_name, MPI_Comm & comm, int myid);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI.
|
||||
int num_procs, myid;
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(comm, &num_procs);
|
||||
MPI_Comm_rank(comm, &myid);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
int bl_type = 1;
|
||||
string lattice_label = "";
|
||||
int order = 1;
|
||||
// int sr = 0, pr = 2;
|
||||
int logging = 0;
|
||||
|
||||
bool visualization = 1;
|
||||
bool visit = true;
|
||||
bool densityCalc = true;
|
||||
bool stiffnessCalc = false;
|
||||
bool bandGapCalc = false;
|
||||
bool band_gap_mid_pts = false;
|
||||
|
||||
double a = -1.0, b = -1.0, c = -1.0;
|
||||
double alpha = -1.0, beta = -1.0, gamma = -1.0;
|
||||
double alpha_deg = -1.0, beta_deg = -1.0, gamma_deg = -1.0;
|
||||
double lcf = 0.3;
|
||||
double density_tol = 0.05;
|
||||
double stiffness_tol = 0.05;
|
||||
double band_gap_tol = 0.05;
|
||||
int band_gap_max_ref = 2;
|
||||
int band_gap_samp_pow = 2;
|
||||
// double lambda = 2.07748e+9;
|
||||
// double mu = 0.729927e+9;
|
||||
// Gallium Arsenide at T=300K
|
||||
// double lambda = 5.34e+11;
|
||||
// double mu = 3.285e+11;
|
||||
// double rho0 = 0.0;
|
||||
|
||||
// Acrylonitrile Butadiene Styrene (ABS)
|
||||
// double rho = 1110.0; // Mass density 1.075 kg/m^3
|
||||
double rho = 1000.0; // Mass density 1.0 kg/m^3
|
||||
double E = 2.0e9; // Young's Modulus 2GPa
|
||||
double nu = 0.4064; // Poisson's Ratio
|
||||
double epsRel = 10.0; // Relative Dielectric Permittivity
|
||||
double muRel = 1.0; // Relative Magnetic Permeability
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&bl_type, "-bl", "--bravais-lattice",
|
||||
"Bravais Lattice Type: \n"
|
||||
" 1 - Primitive Cubic (a),\n"
|
||||
" 2 - Face-Centered Cubic (a),\n"
|
||||
" 3 - Body-Centered Cubic (a),\n"
|
||||
" 4 - Tetragonal (a, c),\n"
|
||||
" 5 - Body-Centered Tetragonal (a, c),\n"
|
||||
" 6 - Orthorhombic (a < b < c),\n"
|
||||
" 7 - Face-Centered Orthorhombic (a < b < c),\n"
|
||||
" 8 - Body-Centered Orthorhombic (a < b < c),\n"
|
||||
" 9 - C-Centered Orthorhombic (a < b, c),\n"
|
||||
" 10 - Hexagonal Prism (a, c),\n"
|
||||
" 11 - Rhombohedral (a, 0 < alpha < pi),\n"
|
||||
" 12 - Monoclinic (a, b <= c, 0 < alpha < pi/2),\n"
|
||||
" 13 - C-Centered Monoclinic (a, b <= c, 0 < alpha < pi/2),\n"
|
||||
" 14 - Triclinic (0 < alpha, beta, gamma < pi)\n"
|
||||
);
|
||||
args.AddOption(&a, "-a", "--lattice-a",
|
||||
"Lattice spacing a");
|
||||
args.AddOption(&b, "-b", "--lattice-b",
|
||||
"Lattice spacing b");
|
||||
args.AddOption(&c, "-c", "--lattice-c",
|
||||
"Lattice spacing c");
|
||||
args.AddOption(&alpha, "-alpha", "--lattice-alpha",
|
||||
"Lattice angle alpha");
|
||||
args.AddOption(&beta, "-beta", "--lattice-beta",
|
||||
"Lattice angle beta");
|
||||
args.AddOption(&gamma, "-gamma", "--lattice-gamma",
|
||||
"Lattice angle gamma");
|
||||
args.AddOption(&alpha_deg, "-alpha-deg", "--lattice-alpha-degrees",
|
||||
"Lattice angle alpha in degrees");
|
||||
args.AddOption(&beta_deg, "-beta-deg", "--lattice-beta-degrees",
|
||||
"Lattice angle beta in degrees");
|
||||
args.AddOption(&gamma_deg, "-gamma-deg", "--lattice-gamma-degrees",
|
||||
"Lattice angle gamma in degrees");
|
||||
args.AddOption(&lcf, "-lcf", "--lattice-coef-frac",
|
||||
"Fraction of inscribed circle radius for rods");
|
||||
args.AddOption(&density_tol, "-rtol", "--density-tolerance",
|
||||
"Stopping tolerance specified as a relative difference "
|
||||
"in computed density");
|
||||
args.AddOption(&stiffness_tol, "-ctol", "--stiffness-tolerance",
|
||||
"Stopping tolerance specified as a relative difference "
|
||||
"in the 2-norm of the computed stiffness tensor");
|
||||
args.AddOption(&band_gap_tol, "-bgtol", "--band-gap-tolerance",
|
||||
"Stopping tolerance specified as a relative difference "
|
||||
"in the computed band gap");
|
||||
args.AddOption(&band_gap_max_ref, "-bgmr", "--band-gap-max-ref",
|
||||
"Maximum number of uniform mesh refinements to perform "
|
||||
"when computing the band gap");
|
||||
args.AddOption(&band_gap_samp_pow, "-bgsp", "--band-gap-samp-pow",
|
||||
"Number of sampling points per segment is 2^samp_pow "
|
||||
"when computing the band gap");
|
||||
args.AddOption(&band_gap_mid_pts, "-bgmp", "--band-gap-mid-pts",
|
||||
"-no-bgmp", "--no-band-gap-mid-pts",
|
||||
"Whether to include mid points in the band gap computation");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree) or -1 for"
|
||||
" isoparametric space.");
|
||||
// args.AddOption(&sr, "-sr", "--serial-refinement",
|
||||
// "Number of serial refinement levels.");
|
||||
// args.AddOption(&pr, "-pr", "--parallel-refinement",
|
||||
// "Number of parallel refinement levels.");
|
||||
// args.AddOption(&prob_, "-p", "--problem-type",
|
||||
// "Problem Geometry.");
|
||||
// args.AddOption(&lambda, "-l", "--lambda",
|
||||
// "Lambda");
|
||||
// args.AddOption(&mu, "-m", "--mu",
|
||||
// "Mu");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&visit, "-visit", "--visit", "-no-visit",
|
||||
"--no-visualization",
|
||||
"Enable or disable VisIt visualization.");
|
||||
args.AddOption(&densityCalc, "-rho", "--density", "-no-rho", "--no-density",
|
||||
"Enable or disable density calculation.");
|
||||
args.AddOption(&stiffnessCalc, "-C", "--stiffness",
|
||||
"-no-C", "--no-stiffness",
|
||||
"Enable or disable stiffness tensor calculation.");
|
||||
// args.AddOption(&dispersionPlot, "-disp", "--dispersion",
|
||||
// "-no-disp", "--no-dispersion",
|
||||
// "Enable or disable dispersion plot calculation.");
|
||||
args.AddOption(&bandGapCalc, "-bg", "--band-gap",
|
||||
"-no-bg", "--no-band-gap",
|
||||
"Enable or disable band gap calculation.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
if ( alpha_deg > 0.0 ) { alpha = alpha_deg * M_PI / 180.0; }
|
||||
if ( beta_deg > 0.0 ) { beta = beta_deg * M_PI / 180.0; }
|
||||
if ( gamma_deg > 0.0 ) { gamma = gamma_deg * M_PI / 180.0; }
|
||||
|
||||
BRAVAIS_LATTICE_TYPE lattice_type = (BRAVAIS_LATTICE_TYPE)(bl_type + 5);
|
||||
BravaisLattice * bravais = BravaisLatticeFactory(lattice_type,
|
||||
a, b, c,
|
||||
alpha, beta, gamma,
|
||||
logging);
|
||||
BravaisLattice3D * bravais3d = dynamic_cast<BravaisLattice3D*>(bravais);
|
||||
|
||||
lattice_label = bravais->GetLatticeTypeLabel();
|
||||
|
||||
if ( myid == 0 )
|
||||
{
|
||||
cout << "Lattice Type: " << lattice_label << endl;
|
||||
}
|
||||
|
||||
bravais3d->GetAxialLengths(a, b, c);
|
||||
bravais3d->GetInteraxialAngles(alpha, beta, gamma);
|
||||
|
||||
ostringstream oss_prefix;
|
||||
oss_prefix << "Meta-Material-" << lattice_label
|
||||
<< "-" << (int)round(100.0*a)
|
||||
<< "-" << (int)round(100.0*b)
|
||||
<< "-" << (int)round(100.0*c)
|
||||
<< "-" << (int)round(180.0*alpha / M_PI)
|
||||
<< "-" << (int)round(180.0*beta / M_PI)
|
||||
<< "-" << (int)round(180.0*gamma / M_PI)
|
||||
<< "-" << (int)round(1000.0*lcf);
|
||||
// << "-r" << sr + pr;
|
||||
|
||||
CreateDirectory(oss_prefix.str(),comm,myid);
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
|
||||
// and volume meshes with the same code.
|
||||
/*
|
||||
Mesh * mesh = bravais->GetPeriodicWignerSeitzMesh();
|
||||
|
||||
int euler = mesh->EulerNumber();
|
||||
if ( myid == 0 ) { cout << "Initial Euler Number: " << euler << endl; }
|
||||
mesh->CheckElementOrientation(false);
|
||||
mesh->CheckBdrElementOrientation(false);
|
||||
|
||||
// 4. Refine the serial mesh on all processors to increase the resolution. In
|
||||
// this example we do 'ref_levels' of uniform refinement.
|
||||
{
|
||||
int ref_levels = sr;
|
||||
for (int l = 0; l < ref_levels; l++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
int euler = mesh->EulerNumber();
|
||||
if ( myid == 0 )
|
||||
{
|
||||
cout << l+1 << ", Refined Euler Number: " << euler << endl;
|
||||
}
|
||||
mesh->CheckElementOrientation(false);
|
||||
mesh->CheckBdrElementOrientation(false);
|
||||
}
|
||||
}
|
||||
*/
|
||||
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
|
||||
// this mesh further in parallel to increase the resolution. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
// ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
|
||||
/*
|
||||
delete mesh;
|
||||
{
|
||||
int par_ref_levels = pr;
|
||||
for (int l = 0; l < par_ref_levels; l++)
|
||||
{
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
*/
|
||||
// L2_ParFESpace * L2FESpace = new L2_ParFESpace(pmesh, 0,
|
||||
// pmesh->Dimension());
|
||||
/*
|
||||
// int nElems = L2FESpace->GetVSize();
|
||||
int nElems = mesh->GetNE();
|
||||
cout << myid << ": nElems = " << nElems << endl;
|
||||
delete mesh;
|
||||
*/
|
||||
// LatticeCoefficient latCoef(*bravais, lcf);
|
||||
|
||||
// ParGridFunction * vf0 = new ParGridFunction(L2FESpace);
|
||||
// ParGridFunction * vf1 = new ParGridFunction(L2FESpace);
|
||||
|
||||
// FunctionCoefficient vfFunc(vol_frac_coef);
|
||||
// vf0->ProjectCoefficient(latCoef);
|
||||
/*
|
||||
vf1->ProjectCoefficient(vfFunc);
|
||||
|
||||
double vf13 = (*vf0)[13];
|
||||
double dvf = 0.01 * (0.5 - vf13);
|
||||
(*vf1)[13] += dvf;
|
||||
*/
|
||||
VisData vd("localhost", 19916, 1440, 900, 238, 238, 10, 45);
|
||||
/*
|
||||
if (visualization)
|
||||
{
|
||||
socketstream vf_sock;
|
||||
VisualizeField(vf_sock, *vf0, "Volume Fraction 0", vd);
|
||||
vd.IncrementWindow();
|
||||
// socketstream vf1_sock;
|
||||
// VisualizeField(vf1_sock, *vf1, "Volume Fraction 1", vd);
|
||||
// vd.IncrementWindow();
|
||||
}
|
||||
*/
|
||||
/*
|
||||
meta_material::Density density(*pmesh, bravais->GetUnitCellVolume(),
|
||||
0.0, rho);
|
||||
|
||||
density.SetVolumeFraction(*vf0);
|
||||
*/
|
||||
if ( myid == 0 )
|
||||
{
|
||||
cout << "Volume of the unit cell: "
|
||||
<< bravais->GetUnitCellVolume() << endl;
|
||||
}
|
||||
|
||||
if (densityCalc)
|
||||
{
|
||||
LatticeCoefficient rhoCoef(*bravais, lcf, 0.0, rho);
|
||||
|
||||
// The density computation does not require a periodic mesh
|
||||
Mesh * mesh_rho = bravais->GetWignerSeitzMesh();
|
||||
mesh_rho->EnsureNCMesh();
|
||||
mesh_rho->UniformRefinement();
|
||||
mesh_rho->UniformRefinement();
|
||||
ParMesh *pmesh_rho = new ParMesh(MPI_COMM_WORLD, *mesh_rho);
|
||||
delete mesh_rho;
|
||||
|
||||
meta_material::Density density(*pmesh_rho, rho,
|
||||
bravais->GetUnitCellVolume(),
|
||||
rhoCoef, density_tol);
|
||||
|
||||
vector<double> effective_rho;
|
||||
density.GetHomogenizedProperties(effective_rho);
|
||||
if ( myid == 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << oss_prefix.str() << "/density.dat";
|
||||
ofstream ofs(oss.str().c_str());
|
||||
|
||||
cout << "Effective Density: ";
|
||||
for (unsigned int i=0; i<effective_rho.size(); i++)
|
||||
{
|
||||
cout << effective_rho[i]; ofs << effective_rho[i];
|
||||
if ( i < effective_rho.size()-1 ) { cout << ", "; ofs << "\t"; }
|
||||
}
|
||||
cout << endl; ofs << endl;
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
if (visualization)
|
||||
{
|
||||
density.InitializeGLVis(vd);
|
||||
density.DisplayToGLVis();
|
||||
}
|
||||
if ( visit )
|
||||
{
|
||||
density.WriteVisItFields(oss_prefix.str(), "Density");
|
||||
}
|
||||
delete pmesh_rho;
|
||||
}
|
||||
|
||||
if (stiffnessCalc)
|
||||
{
|
||||
double lambda = E * nu / ( (1.0 + nu) * (1.0 - 2.0 * nu) );
|
||||
double mu = 0.5 * E / (1.0 + nu);
|
||||
double mat_scale = 1.0e-6;
|
||||
|
||||
LatticeCoefficient lambdaCoef(*bravais, lcf, lambda * mat_scale, lambda);
|
||||
LatticeCoefficient muCoef(*bravais, lcf, mu * mat_scale, mu);
|
||||
/*
|
||||
meta_material::StiffnessTensor elasticity(*pmesh,
|
||||
bravais->GetUnitCellVolume(),
|
||||
lambda * mat_scale, mu * mat_scale,
|
||||
lambda, mu);
|
||||
|
||||
elasticity.SetVolumeFraction(*vf0);
|
||||
*/
|
||||
Mesh * mesh_C = bravais->GetPeriodicWignerSeitzMesh();
|
||||
|
||||
if ( mesh_C->EulerNumber() != 0 )
|
||||
{
|
||||
MFEM_ABORT("Euler number equal to " << mesh_C->EulerNumber()
|
||||
<< ". Periodic Bravais Lattice meshes "
|
||||
"should have Euler number 0!");
|
||||
}
|
||||
|
||||
// mesh_C->UniformRefinement();
|
||||
mesh_C->UniformRefinement();
|
||||
mesh_C->EnsureNCMesh();
|
||||
|
||||
ParMesh *pmesh_C = new ParMesh(MPI_COMM_WORLD, *mesh_C);
|
||||
delete mesh_C;
|
||||
|
||||
meta_material::StiffnessTensor elasticity(*pmesh_C,
|
||||
bravais->GetUnitCellVolume(),
|
||||
lambdaCoef, muCoef,
|
||||
stiffness_tol);
|
||||
|
||||
vector<double> elas;
|
||||
elasticity.GetHomogenizedProperties(elas);
|
||||
if ( myid == 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << oss_prefix.str() << "/stiffness_tensor.dat";
|
||||
ofstream ofs(oss.str().c_str());
|
||||
|
||||
cout << "Effective Elasticity Tensor: " << endl;
|
||||
int k = 0;
|
||||
for (unsigned int i=0; i<6; i++)
|
||||
{
|
||||
for (unsigned int j=0; j<i; j++)
|
||||
{
|
||||
cout << " -----------";
|
||||
ofs << elas[(11 - j) * j / 2 + i] << "\t";
|
||||
}
|
||||
for (unsigned int j=i; j<6; j++)
|
||||
{
|
||||
cout << " " << elas[k]; ofs << elas[k];
|
||||
if ( k < 20 ) { ofs << "\t"; }
|
||||
k++;
|
||||
}
|
||||
cout << endl; ofs << endl;
|
||||
}
|
||||
cout << endl;
|
||||
ofs.close();
|
||||
}
|
||||
if (visualization)
|
||||
{
|
||||
elasticity.InitializeGLVis(vd);
|
||||
elasticity.DisplayToGLVis();
|
||||
}
|
||||
if ( visit )
|
||||
{
|
||||
elasticity.WriteVisItFields(oss_prefix.str(), "StiffnessTensor");
|
||||
}
|
||||
delete pmesh_C;
|
||||
}
|
||||
|
||||
if (bandGapCalc)
|
||||
{
|
||||
LatticeCoefficient epsCoef(*bravais, lcf, 1.0, epsRel);
|
||||
LatticeCoefficient muCoef(*bravais, lcf, 1.0, muRel);
|
||||
|
||||
Mesh * mesh_bg = bravais->GetPeriodicWignerSeitzMesh();
|
||||
|
||||
if ( mesh_bg->EulerNumber() != 0 )
|
||||
{
|
||||
MFEM_ABORT("Euler number equal to " << mesh_bg->EulerNumber()
|
||||
<< ". Periodic Bravais Lattice meshes "
|
||||
"should have Euler number 0!");
|
||||
}
|
||||
// mesh_bg->UniformRefinement();
|
||||
|
||||
ParMesh *pmesh_bg = new ParMesh(MPI_COMM_WORLD, *mesh_bg);
|
||||
delete mesh_bg;
|
||||
|
||||
meta_material::MaxwellBandGap maxwell_bg(*pmesh_bg, *bravais,
|
||||
band_gap_samp_pow,
|
||||
epsCoef, muCoef,
|
||||
band_gap_mid_pts,
|
||||
band_gap_max_ref,
|
||||
band_gap_tol);
|
||||
|
||||
vector<double> bg;
|
||||
maxwell_bg.GetHomogenizedProperties(bg);
|
||||
|
||||
if ( myid == 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << oss_prefix.str() << "/disp.dat";
|
||||
ofstream ofs(oss.str().c_str());
|
||||
|
||||
maxwell_bg.PrintDispersionPlot(ofs);
|
||||
ofs.close();
|
||||
}
|
||||
if (visualization)
|
||||
{
|
||||
maxwell_bg.InitializeGLVis(vd);
|
||||
maxwell_bg.DisplayToGLVis();
|
||||
}
|
||||
if ( visit )
|
||||
{
|
||||
maxwell_bg.WriteVisItFields(oss_prefix.str(), "MaxwellBandGap");
|
||||
}
|
||||
delete pmesh_bg;
|
||||
}
|
||||
|
||||
// delete vf0;
|
||||
// delete vf1;
|
||||
// delete L2FESpace;
|
||||
// delete pmesh;
|
||||
delete bravais;
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
if ( myid == 0 )
|
||||
{
|
||||
cout << "Exiting Main" << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CreateDirectory(const string &dir_name, MPI_Comm & comm, int myid)
|
||||
{
|
||||
int err;
|
||||
#ifndef MFEM_USE_MPI
|
||||
err = mkdir(dir_name.c_str(), 0775);
|
||||
err = (err && (errno != EEXIST)) ? 1 : 0;
|
||||
#else
|
||||
if (myid == 0)
|
||||
{
|
||||
err = mkdir(dir_name.c_str(), 0775);
|
||||
err = (err && (errno != EEXIST)) ? 1 : 0;
|
||||
MPI_Bcast(&err, 1, MPI_INT, 0, comm);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wait for rank 0 to create the directory
|
||||
MPI_Bcast(&err, 1, MPI_INT, 0, comm);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
double
|
||||
distToLine(double ox, double oy, double oz,
|
||||
double tx, double ty, double tz, const Vector & x)
|
||||
{
|
||||
double xo_data[3];
|
||||
double xt_data[3];
|
||||
Vector xo(xo_data, 3);
|
||||
Vector xt(xt_data, 3);
|
||||
|
||||
// xo = x - {ox,oy,oz}
|
||||
xo[0] = x[0] - ox;
|
||||
xo[1] = x[1] - oy;
|
||||
xo[2] = x[2] - oz;
|
||||
|
||||
// xt = cross_product({tx,ty,tz}, xo)
|
||||
xt[0] = ty * xo[2] - tz * xo[1];
|
||||
xt[1] = tz * xo[0] - tx * xo[2];
|
||||
xt[2] = tx * xo[1] - ty * xo[0];
|
||||
|
||||
return xt.Norml2();
|
||||
}
|
||||
double
|
||||
vol_frac_coef(const Vector & x)
|
||||
{
|
||||
switch ( prob_ )
|
||||
{
|
||||
case -1:
|
||||
// Uniform
|
||||
return 1.0;
|
||||
break;
|
||||
case 0:
|
||||
// Slab
|
||||
if ( fabs(x(0)) <= 0.25 ) { return 1.0; }
|
||||
break;
|
||||
case 1:
|
||||
// Cylinder
|
||||
if ( sqrt(x(0)*x(0)+x(1)*x(1)) <= 0.5 ) { return 1.0; }
|
||||
break;
|
||||
case 2:
|
||||
// Sphere
|
||||
if ( x.Norml2() <= 0.5 ) { return 1.0; }
|
||||
break;
|
||||
case 3:
|
||||
// Sphere and 3 Rods
|
||||
{
|
||||
double r1 = 0.14, r2 = 0.36, r3 = 0.105;
|
||||
if ( x.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( x.Norml2() <= r2 ) { return 1.0; }
|
||||
if ( sqrt(x(1)*x(1)+x(2)*x(2)) <= r3 ) { return 1.0; }
|
||||
if ( sqrt(x(2)*x(2)+x(0)*x(0)) <= r3 ) { return 1.0; }
|
||||
if ( sqrt(x(0)*x(0)+x(1)*x(1)) <= r3 ) { return 1.0; }
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
// Sphere and 4 Rods
|
||||
{
|
||||
double r1 = 0.14, r2 = 0.28, r3 = 0.1;
|
||||
if ( x.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( x.Norml2() <= r2 ) { return 1.0; }
|
||||
|
||||
Vector y = x;
|
||||
y[0] -= 0.5; y[1] -= 0.5; y[2] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] -= 0.5; y[1] -= 0.5; y[2] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] -= 0.5; y[1] += 0.5; y[2] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] -= 0.5; y[1] += 0.5; y[2] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] += 0.5; y[1] -= 0.5; y[2] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] += 0.5; y[1] -= 0.5; y[2] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] += 0.5; y[1] += 0.5; y[2] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] += 0.5; y[1] += 0.5; y[2] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
|
||||
double a = r3;
|
||||
double b = 1.0/sqrt(3.0);
|
||||
if ( distToLine(0.0, 0.0, 0.0, b, b, b, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0,-b, b, b, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0,-b,-b, b, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0, b,-b, b, x) <= a ) { return 1.0; }
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
// Two spheres in a BCC configuration
|
||||
if ( x.Norml2() <= 0.3 )
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
int i1 = i%2;
|
||||
int i2 = (i/2)%2;
|
||||
int i4 = i/4;
|
||||
|
||||
Vector u = x;
|
||||
u(0) -= i1?-0.5:0.5;
|
||||
u(1) -= i2?-0.5:0.5;
|
||||
u(2) -= i4?-0.5:0.5;
|
||||
|
||||
if ( u.Norml2() <= 0.2 ) { return 1.0; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
// Sphere and 6 Rods
|
||||
{
|
||||
double r1 = 0.12, r2 = 0.19, r3 = 0.08;
|
||||
if ( x.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( x.Norml2() <= r2 ) { return 1.0; }
|
||||
|
||||
Vector y = x;
|
||||
y[0] -= 0.5; y[1] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] -= 0.5; y[1] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] += 0.5; y[1] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[0] += 0.5; y[1] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
|
||||
y = x; y[1] -= 0.5; y[2] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[1] -= 0.5; y[2] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[1] += 0.5; y[2] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[1] += 0.5; y[2] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
|
||||
y = x; y[2] -= 0.5; y[0] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[2] -= 0.5; y[0] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[2] += 0.5; y[0] -= 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
y = x; y[2] += 0.5; y[0] += 0.5;
|
||||
if ( y.Norml2() <= r1 ) { return 0.0; }
|
||||
if ( y.Norml2() <= r2 ) { return 1.0; }
|
||||
|
||||
double a = r3;
|
||||
double b = 1.0/sqrt(2.0);
|
||||
if ( distToLine(0.0, 0.0, 0.0, b, b, 0, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0, b,-b, 0, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0, b, 0, b, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0, b, 0,-b, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0, 0, b, b, x) <= a ) { return 1.0; }
|
||||
if ( distToLine(0.0, 0.0, 0.0, 0, b,-b, x) <= a ) { return 1.0; }
|
||||
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if ( fabs(x(1)) + fabs(x(2)) < 0.25 ||
|
||||
fabs(x(0)) + fabs(x(2)) < 0.25 ||
|
||||
fabs(x(0)) + fabs(x(1) - 0.5) < 0.25 )
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,731 +0,0 @@
|
||||
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
|
||||
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
|
||||
// reserved. See file COPYRIGHT for details.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability see http://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU Lesser General Public License (as published by the Free
|
||||
// Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
#ifndef MFEM_META_MATERIAL_SOLVER
|
||||
#define MFEM_META_MATERIAL_SOLVER
|
||||
|
||||
#include "../../config/config.hpp"
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
|
||||
#include "../common/pfem_extras.hpp"
|
||||
#include "../common/bravais.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void dsygv_(int *ITYPE, char *JOBZ, char *UPLO, int *N,
|
||||
double *A, int * LDA, double *B, int *LDB, double *W,
|
||||
double *WORK, int *LWORK, int *INFO);
|
||||
}
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
using common::H1_ParFESpace;
|
||||
using common::ND_ParFESpace;
|
||||
using common::RT_ParFESpace;
|
||||
using common::L2_ParFESpace;
|
||||
using common::ParDiscreteGradOperator;
|
||||
using common::ParDiscreteCurlOperator;
|
||||
using common::ParDiscreteInterpolationOperator;
|
||||
using common::VisData;
|
||||
using bravais::BravaisLattice;
|
||||
|
||||
namespace meta_material
|
||||
{
|
||||
|
||||
class LinearCoefficient : public GridFunctionCoefficient
|
||||
{
|
||||
public:
|
||||
LinearCoefficient(GridFunction * gf, double a0, double a1);
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
double GetSensitivity(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{ return (c1_ - c0_); }
|
||||
|
||||
private:
|
||||
double c0_;
|
||||
double c1_;
|
||||
};
|
||||
/*
|
||||
class PenaltyCoefficient : public GridFunctionCoefficient
|
||||
{
|
||||
public:
|
||||
PenaltyCoefficient(GridFunction * gf, int penalty, double a0, double a1);
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
double GetSensitivity(ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
int penalty_;
|
||||
double c0_;
|
||||
double c1_;
|
||||
};
|
||||
*/
|
||||
class Homogenization
|
||||
{
|
||||
public:
|
||||
Homogenization(MPI_Comm comm);
|
||||
virtual ~Homogenization() {}
|
||||
|
||||
void SetVolumeFraction(ParGridFunction & vf) { vf_ = &vf; newVF_ = true; }
|
||||
|
||||
virtual void GetHomogenizedProperties(std::vector<double> & p) = 0;
|
||||
virtual void GetPropertySensitivities(std::vector<ParGridFunction> & dp)
|
||||
= 0;
|
||||
|
||||
void InitializeGLVis(VisData & vd) {}
|
||||
|
||||
void DisplayToGLVis() {}
|
||||
|
||||
void WriteVisItFields(const std::string & prefix,
|
||||
const std::string & label) {}
|
||||
|
||||
protected:
|
||||
MPI_Comm comm_;
|
||||
int myid_;
|
||||
int numProcs_;
|
||||
bool newVF_;
|
||||
|
||||
ParGridFunction * vf_;
|
||||
};
|
||||
|
||||
class Density : public Homogenization
|
||||
{
|
||||
public:
|
||||
// Density(ParMesh & pmesh, double vol,
|
||||
// double rho0, double rho1);
|
||||
Density(ParMesh & pmesh, double refDensity, double vol,
|
||||
Coefficient &rhoCoef, double tol = 0.05);
|
||||
~Density();
|
||||
|
||||
// void SetVolumeFraction(ParGridFunction & vf);
|
||||
|
||||
void GetHomogenizedProperties(std::vector<double> & p);
|
||||
void GetPropertySensitivities(std::vector<ParGridFunction> & dp) {}
|
||||
|
||||
void InitializeGLVis(VisData & vd);
|
||||
|
||||
void DisplayToGLVis();
|
||||
|
||||
void WriteVisItFields(const std::string & prefix,
|
||||
const std::string & label);
|
||||
|
||||
private:
|
||||
void updateRho();
|
||||
|
||||
ParMesh * pmesh_;
|
||||
L2_ParFESpace * L2FESpace_;
|
||||
ParGridFunction * rho_;
|
||||
ParGridFunction * divGradRho_;
|
||||
ParLinearForm * cellVol_;
|
||||
|
||||
// LinearCoefficient rhoCoef_;
|
||||
Coefficient * rhoCoef_;
|
||||
ConstantCoefficient one_;
|
||||
|
||||
double refDensity_;
|
||||
double vol_;
|
||||
double tol_;
|
||||
|
||||
VisData * vd_;
|
||||
socketstream * sock_;
|
||||
socketstream * sock2_;
|
||||
};
|
||||
|
||||
class StiffnessTensor : public Homogenization
|
||||
{
|
||||
public:
|
||||
/*
|
||||
StiffnessTensor(ParMesh & pmesh, double vol,
|
||||
double lambda0, double mu0,
|
||||
double lambda1, double mu1);
|
||||
*/
|
||||
StiffnessTensor(ParMesh & pmesh, double vol,
|
||||
Coefficient &lambdaCoef, Coefficient &muCoef,
|
||||
double tol = 0.05);
|
||||
~StiffnessTensor();
|
||||
|
||||
// void SetVolumeFraction(ParGridFunction & vf);
|
||||
|
||||
void GetHomogenizedProperties(std::vector<double> & p);
|
||||
void GetPropertySensitivities(std::vector<ParGridFunction> & dp) {}
|
||||
|
||||
void InitializeGLVis(VisData & vd);
|
||||
|
||||
void DisplayToGLVis();
|
||||
|
||||
void WriteVisItFields(const std::string & prefix,
|
||||
const std::string & label);
|
||||
|
||||
private:
|
||||
|
||||
void TensorGradient(const Vector & x, Vector & y);
|
||||
void TensorGradientTranspose(const Vector & x, Vector & y);
|
||||
void TensorMassMatrix(const Vector & x, Vector & y);
|
||||
void RestrictedTensorMassMatrix(int r, const Vector & x, Vector & y);
|
||||
void RestrictedVectorAdd(int r, const Vector & x, Vector & y);
|
||||
|
||||
// Produces a 2-tensor coefficient for the diagonal portion of an
|
||||
// elasticity operator. The coefficient is defined by:
|
||||
// / lambda + 2 * mu, i == j == axis
|
||||
// K = | mu, i == j != axis
|
||||
// \ 0, i != j
|
||||
class DiagElasticityCoef : public MatrixCoefficient
|
||||
{
|
||||
public:
|
||||
DiagElasticityCoef(Coefficient & lambda,
|
||||
Coefficient & mu,
|
||||
int axis);
|
||||
|
||||
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
int axis_;
|
||||
Coefficient * lambda_;
|
||||
Coefficient * mu_;
|
||||
};
|
||||
|
||||
// Produces a 2-tensor coefficient for the off-diagonal portion of an
|
||||
// elasticity operator. The coefficient is defined by:
|
||||
// / lambda, i == axis0, j == axis1
|
||||
// K = | mu, i == axis1, j == axis0
|
||||
// \ 0, otherwise
|
||||
class OffDiagElasticityCoef : public MatrixCoefficient
|
||||
{
|
||||
public:
|
||||
OffDiagElasticityCoef(Coefficient & lambda,
|
||||
Coefficient & mu,
|
||||
int axis0, int axis1);
|
||||
|
||||
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
int axis0_;
|
||||
int axis1_;
|
||||
Coefficient * lambda_;
|
||||
Coefficient * mu_;
|
||||
};
|
||||
|
||||
void solve(const Vector & E, Vector & Chi);
|
||||
|
||||
int dim_;
|
||||
int irOrder_;
|
||||
int geom_;
|
||||
bool amg_elast_;
|
||||
|
||||
ParMesh * pmesh_;
|
||||
|
||||
L2_ParFESpace * L2FESpace_;
|
||||
L2_ParFESpace * L2VFESpace_;
|
||||
H1_ParFESpace * H1FESpace_;
|
||||
H1_ParFESpace * H1VFESpace_;
|
||||
ND_ParFESpace * HCurlFESpace_;
|
||||
ND_ParFESpace * HCurlVFESpace_;
|
||||
RT_ParFESpace * HDivFESpace_;
|
||||
|
||||
// LinearCoefficient lambdaCoef_;
|
||||
// LinearCoefficient muCoef_;
|
||||
Coefficient * lambdaCoef_;
|
||||
Coefficient * muCoef_;
|
||||
|
||||
DiagElasticityCoef xxCoef_;
|
||||
DiagElasticityCoef yyCoef_;
|
||||
DiagElasticityCoef zzCoef_;
|
||||
OffDiagElasticityCoef yzCoef_;
|
||||
OffDiagElasticityCoef xzCoef_;
|
||||
OffDiagElasticityCoef xyCoef_;
|
||||
|
||||
ParGridFunction * lambda_;
|
||||
ParGridFunction * mu_;
|
||||
|
||||
ParBilinearForm * a_;
|
||||
ParBilinearForm * m_[6];
|
||||
ParGridFunction * Chi_[6];
|
||||
ParGridFunction * E_[3];
|
||||
ParGridFunction * F_[6];
|
||||
ParLinearForm * MF_[6];
|
||||
|
||||
ParDiscreteGradOperator * grad_;
|
||||
|
||||
BilinearFormIntegrator * diffInteg_[3];
|
||||
ParGridFunction * errSol_;
|
||||
ErrorEstimator * errEst_[3];
|
||||
ParGridFunction * errors_[4];
|
||||
|
||||
ParGridFunction * b_;
|
||||
// HypreParVector * tmp1_;
|
||||
|
||||
double vol_;
|
||||
double tol_;
|
||||
|
||||
VisData * vd_;
|
||||
socketstream socks_[8];
|
||||
socketstream err_socks_[4];
|
||||
|
||||
int seqVF_;
|
||||
};
|
||||
|
||||
class ParDiscreteVectorProductOperator
|
||||
: public ParDiscreteInterpolationOperator
|
||||
{
|
||||
public:
|
||||
ParDiscreteVectorProductOperator(ParFiniteElementSpace *dfes,
|
||||
ParFiniteElementSpace *rfes,
|
||||
const Vector & v);
|
||||
|
||||
private:
|
||||
VectorConstantCoefficient vCoef_;
|
||||
};
|
||||
|
||||
class ParDiscreteVectorCrossProductOperator
|
||||
: public ParDiscreteInterpolationOperator
|
||||
{
|
||||
public:
|
||||
ParDiscreteVectorCrossProductOperator(ParFiniteElementSpace *dfes,
|
||||
ParFiniteElementSpace *rfes,
|
||||
const Vector & v);
|
||||
private:
|
||||
VectorConstantCoefficient vCoef_;
|
||||
};
|
||||
|
||||
//class MaxwellBlochWaveEquation;
|
||||
//class MaxwellBlochWaveEquation::MaxwellBlochWaveProjector;
|
||||
|
||||
class MaxwellBlochWaveEquation
|
||||
{
|
||||
public:
|
||||
MaxwellBlochWaveEquation(ParMesh & pmesh,
|
||||
int order);
|
||||
~MaxwellBlochWaveEquation();
|
||||
|
||||
// Where kappa is the phase shift vector
|
||||
void SetKappa(const Vector & kappa);
|
||||
|
||||
// Where beta*zeta = kappa
|
||||
void SetBeta(double beta);
|
||||
void SetZeta(const Vector & zeta);
|
||||
|
||||
// void SetAzimuth(double alpha_a);
|
||||
// void SetInclination(double alpha_i);
|
||||
|
||||
// void SetOmega(double omega);
|
||||
void SetAbsoluteTolerance(double atol);
|
||||
void SetNumEigs(int nev);
|
||||
void SetMassCoef(Coefficient & m);
|
||||
void SetStiffnessCoef(Coefficient & k);
|
||||
|
||||
void Setup();
|
||||
|
||||
void SetInitialVectors(int num_vecs, HypreParVector ** vecs);
|
||||
|
||||
// void SetBravaisLattice(BravaisLattice & bravais) { bravais_ = &bravais; }
|
||||
|
||||
void Update();
|
||||
|
||||
/// Solve the eigenproblem
|
||||
void Solve();
|
||||
|
||||
/// Collect the converged eigenvalues
|
||||
void GetEigenvalues(std::vector<double> & eigenvalues);
|
||||
|
||||
/// A convenience method which combines six methods into one
|
||||
void GetEigenvalues(int nev, const Vector & kappa,
|
||||
std::vector<HypreParVector*> & init_vecs,
|
||||
std::vector<double> & eigenvalues);
|
||||
|
||||
/// Extract a single eigenvector
|
||||
HypreParVector * ReturnEigenvector(unsigned int i);
|
||||
|
||||
void CopyEigenvector(unsigned int i,
|
||||
HypreParVector & V);
|
||||
|
||||
void GetEigenvector(unsigned int i,
|
||||
HypreParVector & Er,
|
||||
HypreParVector & Ei,
|
||||
HypreParVector & Br,
|
||||
HypreParVector & Bi);
|
||||
void GetEigenvectorE(unsigned int i,
|
||||
HypreParVector & Er,
|
||||
HypreParVector & Ei);
|
||||
void GetEigenvectorB(unsigned int i,
|
||||
HypreParVector & Br,
|
||||
HypreParVector & Bi);
|
||||
|
||||
BlockOperator * GetAOperator() { return A_; }
|
||||
BlockOperator * GetMOperator() { return M_; }
|
||||
|
||||
Solver * GetPreconditioner() { return Precond_; }
|
||||
Operator * GetSubSpaceProjector() { return SubSpaceProj_; }
|
||||
|
||||
ParFiniteElementSpace * GetH1FESpace() { return H1FESpace_; }
|
||||
ParFiniteElementSpace * GetHCurlFESpace() { return HCurlFESpace_; }
|
||||
ParFiniteElementSpace * GetHDivFESpace() { return HDivFESpace_; }
|
||||
|
||||
// void TestVector(const HypreParVector & v);
|
||||
|
||||
ParGridFunction * GetEigenvectorEnergy(unsigned int i) { return energy_[i]; }
|
||||
|
||||
void GetFourierCoefficients(HypreParVector & Vr,
|
||||
HypreParVector & Vi,
|
||||
Array2D<double> &f);
|
||||
|
||||
void IdentifyDegeneracies(double zero_tol, double rel_tol,
|
||||
std::vector<std::set<int> > & degen);
|
||||
|
||||
void GetFieldAverages(unsigned int i,
|
||||
Vector & Er, Vector & Ei,
|
||||
Vector & Br, Vector & Bi,
|
||||
Vector & Dr, Vector & Di,
|
||||
Vector & Hr, Vector & Hi);
|
||||
|
||||
void ComputeHomogenizedCoefs();
|
||||
|
||||
void DetermineBasis(const Vector & v1, std::vector<Vector> & e);
|
||||
|
||||
void WriteVisitFields(const std::string & prefix,
|
||||
const std::string & label);
|
||||
|
||||
void GetSolverStats(double &meanTime, double &stdDevTime,
|
||||
double &meanIter, double &stdDevIter,
|
||||
int &nSolves);
|
||||
|
||||
void TestProjector() const;
|
||||
|
||||
private:
|
||||
|
||||
MPI_Comm comm_;
|
||||
int myid_;
|
||||
int hcurl_loc_size_;
|
||||
int hdiv_loc_size_;
|
||||
int nev_;
|
||||
|
||||
bool newBeta_;
|
||||
bool newZeta_;
|
||||
bool newOmega_;
|
||||
bool newMCoef_;
|
||||
bool newKCoef_;
|
||||
|
||||
ParMesh * pmesh_;
|
||||
H1_ParFESpace * H1FESpace_;
|
||||
ND_ParFESpace * HCurlFESpace_;
|
||||
RT_ParFESpace * HDivFESpace_;
|
||||
// L2_ParFESpace * L2FESpace_;
|
||||
|
||||
// BravaisLattice * bravais_;
|
||||
// HCurlFourierSeries * fourierHCurl_;
|
||||
|
||||
double atol_;
|
||||
double beta_;
|
||||
|
||||
Vector zeta_;
|
||||
Vector kappa_;
|
||||
|
||||
Coefficient * mCoef_;
|
||||
Coefficient * kCoef_;
|
||||
|
||||
Array<int> block_offsets_;
|
||||
Array<int> block_trueOffsets_;
|
||||
Array<int> block_trueOffsets2_;
|
||||
Array<HYPRE_Int> tdof_offsets_;
|
||||
|
||||
BlockOperator * A_;
|
||||
BlockOperator * M_;
|
||||
BlockOperator * C_;
|
||||
|
||||
BlockVector * blkHCurl_;
|
||||
BlockVector * blkHDiv_;
|
||||
|
||||
HypreParMatrix * M1_;
|
||||
HypreParMatrix * M2_;
|
||||
HypreParMatrix * S1_;
|
||||
HypreParMatrix * T1_;
|
||||
HypreParMatrix * T12_;
|
||||
HypreParMatrix * Z12_;
|
||||
|
||||
HypreParMatrix * DKZ_;
|
||||
// HypreParMatrix * DKZT_;
|
||||
|
||||
HypreAMS * T1Inv_;
|
||||
|
||||
ParDiscreteCurlOperator * Curl_;
|
||||
ParDiscreteVectorCrossProductOperator * Zeta_;
|
||||
|
||||
BlockDiagonalPreconditioner * BDP_;
|
||||
|
||||
Solver * Precond_;
|
||||
//MaxwellBlochWaveProjector * SubSpaceProj_;
|
||||
Operator * SubSpaceProj_;
|
||||
|
||||
HypreParVector ** vecs_;
|
||||
HypreParVector * vec0_;
|
||||
|
||||
HypreLOBPCG * lobpcg_;
|
||||
HypreAME * ame_;
|
||||
|
||||
ParGridFunction ** energy_;
|
||||
/*
|
||||
HypreParVector * AvgHCurl_coskx_[3];
|
||||
HypreParVector * AvgHCurl_sinkx_[3];
|
||||
HypreParVector * AvgHDiv_coskx_[3];
|
||||
HypreParVector * AvgHDiv_sinkx_[3];
|
||||
|
||||
HypreParVector * AvgHCurl_eps_coskx_[3];
|
||||
HypreParVector * AvgHCurl_eps_sinkx_[3];
|
||||
HypreParVector * AvgHDiv_muInv_coskx_[3];
|
||||
HypreParVector * AvgHDiv_muInv_sinkx_[3];
|
||||
*/
|
||||
std::vector<double> solve_times_;
|
||||
std::vector<int> solve_iters_;
|
||||
|
||||
class MaxwellBlochWavePrecond : public Solver
|
||||
{
|
||||
public:
|
||||
MaxwellBlochWavePrecond(ParFiniteElementSpace & HCurlFESpace,
|
||||
BlockDiagonalPreconditioner & BDP,
|
||||
Operator & subSpaceProj,
|
||||
double w);
|
||||
|
||||
~MaxwellBlochWavePrecond();
|
||||
|
||||
void Mult(const Vector & x, Vector & y) const;
|
||||
|
||||
void SetOperator(const Operator & A);
|
||||
|
||||
private:
|
||||
int myid_;
|
||||
|
||||
// ParFiniteElementSpace * HCurlFESpace_;
|
||||
BlockDiagonalPreconditioner * BDP_;
|
||||
const Operator * A_;
|
||||
Operator * subSpaceProj_;
|
||||
// mutable HypreParVector *r_, *u_, *v_;
|
||||
mutable HypreParVector *u_;
|
||||
// double w_;
|
||||
};
|
||||
|
||||
class MaxwellBlochWaveProjector : public Operator
|
||||
{
|
||||
public:
|
||||
MaxwellBlochWaveProjector(ParFiniteElementSpace & HCurlFESpace,
|
||||
ParFiniteElementSpace & H1FESpace,
|
||||
BlockOperator & M,
|
||||
double beta, const Vector & zeta);
|
||||
~MaxwellBlochWaveProjector();
|
||||
|
||||
void SetBeta(double beta);
|
||||
void SetZeta(const Vector & zeta);
|
||||
|
||||
void Setup();
|
||||
virtual void Mult(const Vector &x, Vector &y) const;
|
||||
|
||||
private:
|
||||
int myid_;
|
||||
int locSize_;
|
||||
|
||||
bool newBeta_;
|
||||
bool newZeta_;
|
||||
|
||||
ParFiniteElementSpace * HCurlFESpace_;
|
||||
ParFiniteElementSpace * H1FESpace_;
|
||||
|
||||
double beta_;
|
||||
Vector zeta_;
|
||||
|
||||
HypreParMatrix * T01_;
|
||||
HypreParMatrix * Z01_;
|
||||
HypreParMatrix * A0_;
|
||||
HypreParMatrix * DKZ_;
|
||||
|
||||
MINRESSolver * minres_;
|
||||
|
||||
Array<int> block_offsets0_;
|
||||
Array<int> block_offsets1_;
|
||||
Array<int> block_trueOffsets0_;
|
||||
Array<int> block_trueOffsets1_;
|
||||
|
||||
BlockOperator * S0_;
|
||||
BlockOperator * M_;
|
||||
BlockOperator * G_;
|
||||
|
||||
mutable HypreParVector * urDummy_;
|
||||
mutable HypreParVector * uiDummy_;
|
||||
mutable HypreParVector * vrDummy_;
|
||||
mutable HypreParVector * viDummy_;
|
||||
|
||||
mutable BlockVector * u0_;
|
||||
mutable BlockVector * v0_;
|
||||
mutable BlockVector * u1_;
|
||||
mutable BlockVector * v1_;
|
||||
};
|
||||
};
|
||||
|
||||
class InverseCoefficient : public TransformedCoefficient
|
||||
{
|
||||
public:
|
||||
InverseCoefficient(Coefficient * q) : TransformedCoefficient(q, inv_) {}
|
||||
private:
|
||||
static double inv_(double v) { return 1.0/v; }
|
||||
};
|
||||
|
||||
class MaxwellBlochWaveSolver
|
||||
{
|
||||
public:
|
||||
MaxwellBlochWaveSolver(ParMesh & pmesh, BravaisLattice & bravais,
|
||||
Coefficient & epsCoef, Coefficient & muCoef,
|
||||
int max_ref = 2, int nev = 24, double tol = 0.05);
|
||||
~MaxwellBlochWaveSolver();
|
||||
|
||||
// Where kappa is the phase shift vector
|
||||
void SetKappa(const Vector & kappa);
|
||||
|
||||
// Where beta*zeta = kappa and |zeta| = 1
|
||||
void SetBeta(double beta);
|
||||
void SetZeta(const Vector & zeta);
|
||||
|
||||
void GetEigenfrequencies(std::vector<double> & omega);
|
||||
|
||||
MaxwellBlochWaveEquation * GetFineSolver()
|
||||
{ return mbwe_[mbwe_.size()-1]; }
|
||||
|
||||
HypreParVector * ReturnFineEigenvector(int i);
|
||||
|
||||
void InitializeGLVis(VisData & vd);
|
||||
|
||||
void DisplayToGLVis();
|
||||
|
||||
void WriteVisItFields(const std::string & prefix,
|
||||
const std::string & label);
|
||||
|
||||
private:
|
||||
|
||||
void createPartitioning(ParFiniteElementSpace & pfes, HYPRE_Int *& part);
|
||||
|
||||
int max_lvl_;
|
||||
int nev_;
|
||||
double tol_;
|
||||
|
||||
std::vector<ParMesh*> pmesh_;
|
||||
std::vector<MaxwellBlochWaveEquation*> mbwe_;
|
||||
std::vector<const Operator*> refineOp_;
|
||||
std::vector<std::pair<HypreParVector*, HypreParVector*> > EField_;
|
||||
//std::vector<std::vector<std::pair<ParGridFunction,
|
||||
// ParGridFunction> > > efield_;
|
||||
std::vector<std::pair<ParGridFunction*, ParGridFunction*> > efield_;
|
||||
std::vector<std::vector<HypreParVector*> > initialVecs_;
|
||||
std::vector<int> locSize_;
|
||||
std::vector<HYPRE_Int*> part_;
|
||||
|
||||
Vector kappa_;
|
||||
Coefficient * epsCoef_;
|
||||
InverseCoefficient muInvCoef_;
|
||||
|
||||
// Coefficient * muCoef_;
|
||||
|
||||
};
|
||||
|
||||
class MaxwellDispersion
|
||||
{
|
||||
public:
|
||||
MaxwellDispersion(ParMesh & pmesh, BravaisLattice & bravais,
|
||||
int sample_power,
|
||||
Coefficient & epsCoef, Coefficient & muCoef,
|
||||
bool midPts = false, int max_ref = 2,
|
||||
int nev = 24, double tol = 0.05);
|
||||
~MaxwellDispersion();
|
||||
|
||||
const std::vector<std::vector<std::map<int,std::vector<double> > > > &
|
||||
GetDispersionData();
|
||||
|
||||
void PrintDispersionPlot(std::ostream & os);
|
||||
|
||||
void InitializeGLVis(VisData & vd);
|
||||
|
||||
void DisplayToGLVis();
|
||||
|
||||
void WriteVisItFields(const std::string & prefix,
|
||||
const std::string & label);
|
||||
|
||||
private:
|
||||
|
||||
void buildRawBasis();
|
||||
|
||||
void approxEigenfrequencies(std::vector<double> & omega);
|
||||
|
||||
void traverseBrillouinZone();
|
||||
|
||||
std::string modLabel(const std::string & label) const;
|
||||
|
||||
void findAndReplace(const std::string & f, const std::string & r,
|
||||
std::string & str) const;
|
||||
|
||||
BravaisLattice * bravais_;
|
||||
MaxwellBlochWaveSolver * mbws_;
|
||||
|
||||
HypreParVector * Ax_;
|
||||
HypreParVector * Mx_;
|
||||
|
||||
DenseMatrix A_;
|
||||
DenseMatrix M_;
|
||||
|
||||
std::vector<HypreParVector*> rawBasis_;
|
||||
std::vector<HypreParVector*> projBasis_;
|
||||
|
||||
std::map<std::string,std::vector<double> > sp_eigs_;
|
||||
std::vector<std::vector<std::map<int,std::vector<double> > > > seg_eigs_;
|
||||
|
||||
int n_pow_;
|
||||
int n_div_;
|
||||
int samp_pow_;
|
||||
int nev_;
|
||||
|
||||
bool midPts_;
|
||||
};
|
||||
|
||||
class MaxwellBandGap : public Homogenization
|
||||
{
|
||||
public:
|
||||
MaxwellBandGap(ParMesh & pmesh, BravaisLattice & bravais,
|
||||
int samp_pow,
|
||||
Coefficient & epsCoef, Coefficient & muCoef,
|
||||
bool midPts = false, int max_ref = 2, double tol = 0.05);
|
||||
~MaxwellBandGap();
|
||||
|
||||
void GetHomogenizedProperties(std::vector<double> & p);
|
||||
void GetPropertySensitivities(std::vector<ParGridFunction> & dp) {}
|
||||
|
||||
void PrintDispersionPlot(std::ostream & os);
|
||||
|
||||
void InitializeGLVis(VisData & vd);
|
||||
|
||||
void DisplayToGLVis();
|
||||
|
||||
void WriteVisItFields(const std::string & prefix,
|
||||
const std::string & label);
|
||||
private:
|
||||
|
||||
MaxwellDispersion * disp_;
|
||||
};
|
||||
|
||||
} // namespace meta_material
|
||||
} // namespace mfem
|
||||
|
||||
#endif // MFEM_USE_MPI
|
||||
|
||||
#endif // MFEM_META_MATERIAL_SOLVER
|
||||
@@ -461,7 +461,7 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
|
||||
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg(); // z = -z
|
||||
K->ParallelEliminateTDofsInRHS(ess_tdof_list, u, z);
|
||||
K->EliminateVDofsInRHS(ess_tdof_list, u, z);
|
||||
|
||||
M_solver.Mult(z, du_dt);
|
||||
du_dt.Print();
|
||||
@@ -483,7 +483,7 @@ void ConductionOperator::ImplicitSolve(const real_t dt,
|
||||
MFEM_VERIFY(dt == current_dt, ""); // SDIRK methods use the same dt
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg();
|
||||
K->ParallelEliminateTDofsInRHS(ess_tdof_list, u, z);
|
||||
K->EliminateVDofsInRHS(ess_tdof_list, u, z);
|
||||
|
||||
T_solver.Mult(z, du_dt);
|
||||
du_dt.SetSubVector(ess_tdof_list, 0.0);
|
||||
|
||||
@@ -7,18 +7,8 @@
|
||||
|
||||
https://mfem.org
|
||||
|
||||
FIXME: this file needs to be updated
|
||||
|
||||
This directory contains utility scripts related to GitLab testing at LLNL.
|
||||
|
||||
* `build_and_test_setup` is used in CI to setup certain directories before
|
||||
running the tests.
|
||||
|
||||
This script was designed to be used in CI context. It is easier for the sake
|
||||
of reproducibility to clone MFEM `data` and `autotest` repository manually
|
||||
next to your MFEM repository, _unless you are using the inline reproducer
|
||||
provided in CI, in which case the required variables will be set for you._
|
||||
|
||||
* `build_and_test` is used in CI to build TPLs (dependencies) and MFEM and to
|
||||
perform testing.
|
||||
|
||||
|
||||
+53
-210
@@ -11,12 +11,6 @@
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Initialize modules for users not using bash as a default shell
|
||||
if test -e /usr/share/lmod/lmod/init/bash
|
||||
then
|
||||
. /usr/share/lmod/lmod/init/bash
|
||||
fi
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
@@ -66,40 +60,15 @@ function usage()
|
||||
}
|
||||
|
||||
project_dir="$(pwd)"
|
||||
hostname="$(hostname)"
|
||||
|
||||
spec=""
|
||||
mode=""
|
||||
spec=""
|
||||
data_dir=""
|
||||
with_data=false
|
||||
|
||||
sys_type=${SYS_TYPE:-""}
|
||||
|
||||
threads=${THREADS:-""}
|
||||
module_list=${MODULE_LIST:-""}
|
||||
job_unique_id=${CI_JOB_ID:-""}
|
||||
use_dev_shm=${USE_DEV_SHM:-true}
|
||||
spack_debug=${SPACK_DEBUG:-false}
|
||||
debug_mode=${DEBUG_MODE:-false}
|
||||
|
||||
# CI_REGISTRY_USER, CI_REGISTRY_IMAGE, and CI_JOB_TOKEN are automatically set by
|
||||
# Gitlab, see https://docs.gitlab.com/ee/ci/variables/predefined_variables.html.
|
||||
# The Spack build cache files can be viewed from the Gitlab web interface under
|
||||
# "Deploy" -> "Container Registry".
|
||||
#
|
||||
# Since the CI_<VARIABLES> are only set in CI, we provide sensible defaults for
|
||||
# usage outside CI context (e.g. to reproduce a CI scenario locally).
|
||||
#
|
||||
# REGISTRY_TOKEN when set allows to provide our own personal access token to
|
||||
# the CI registry. Be sure to set the token with at least read access to the
|
||||
# registry. It is optional outside CI but will speed up the build if many
|
||||
# dependencies are needed.
|
||||
#
|
||||
registry_token=${REGISTRY_TOKEN:-""}
|
||||
ci_registry_user=${CI_REGISTRY_USER:-"${USER}"}
|
||||
ci_registry_image=${CI_REGISTRY_IMAGE:-"czregistry.llnl.gov:5050/mfem/mfem-autotest"}
|
||||
ci_registry_token=${CI_JOB_TOKEN:-"${registry_token}"}
|
||||
|
||||
spec_tab=()
|
||||
|
||||
# Options
|
||||
while [[ $# -gt 0 ]]
|
||||
@@ -108,19 +77,9 @@ do
|
||||
|
||||
case $key in
|
||||
--spec)
|
||||
shift
|
||||
arg="${1}"
|
||||
if [[ "${arg}" =~ ^\" ]]; then
|
||||
arg="${arg#\"}"
|
||||
while [[ ! "${arg}" =~ [^\\]\"$ ]]; do
|
||||
spec_tab+=("${arg}")
|
||||
shift
|
||||
arg="${1}"
|
||||
done
|
||||
arg="${arg%\"}"
|
||||
fi
|
||||
spec_tab+=("${arg}")
|
||||
shift
|
||||
spec="$2"
|
||||
shift # past argument
|
||||
shift # past value
|
||||
;;
|
||||
--deps-only|--build-only|--test-only)
|
||||
mode="$key"
|
||||
@@ -140,133 +99,48 @@ do
|
||||
exit 0;
|
||||
;;
|
||||
*) # unknown option
|
||||
echo "[Error]: option $key is unknown"
|
||||
echo "ERROR: option $key is unknown"
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
spec="${spec_tab[@]}"
|
||||
|
||||
timed_message ()
|
||||
{
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "~ $(date --rfc-3339=seconds) ~ ${1}"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
}
|
||||
|
||||
at_exit()
|
||||
{
|
||||
if [[ "${debug_mode}" != "true" ]]; then
|
||||
if [[ "${#exit_rm_list[@]}" != 0 ]]; then
|
||||
echo ${script_name}:at_exit: rm -rf "${exit_rm_list[@]}"
|
||||
rm -rf "${exit_rm_list[@]}"
|
||||
fi
|
||||
if [[ "${exit_distclean}" == 1 ]]; then
|
||||
echo ${script_name}:at_exit: \
|
||||
make -C "${project_dir}" distclean "> /dev/null 2>&1"
|
||||
make -C "${project_dir}" distclean > /dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ ${debug_mode} == true ]]
|
||||
then
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "~~~~~ Debug mode:"
|
||||
echo "~~~~~ - Spack debug mode."
|
||||
echo "~~~~~ - Deactivated shared memory."
|
||||
echo "~~~~~ - Do not push to buildcache."
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
use_dev_shm=false
|
||||
spack_debug=true
|
||||
fi
|
||||
|
||||
if [[ -n ${module_list} ]]
|
||||
then
|
||||
timed_message "Modules to load: ${module_list}"
|
||||
module load ${module_list}
|
||||
fi
|
||||
|
||||
prefix=""
|
||||
|
||||
if [[ -d /dev/shm && ${use_dev_shm} == true ]]
|
||||
then
|
||||
prefix="/dev/shm/${hostname}"
|
||||
if [[ -z ${job_unique_id} ]]; then
|
||||
job_unique_id=manual_job_$(date +%s)
|
||||
while [[ -d ${prefix}-${job_unique_id} ]] ; do
|
||||
sleep 1
|
||||
job_unique_id=manual_job_$(date +%s)
|
||||
done
|
||||
fi
|
||||
|
||||
prefix="${prefix}-${job_unique_id}"
|
||||
else
|
||||
# We set the prefix in the parent directory so that spack dependencies are
|
||||
# not installed inside the source tree.
|
||||
prefix="${project_dir}/../spack-and-build-root"
|
||||
fi
|
||||
|
||||
echo "Creating directory ${prefix}"
|
||||
echo "project_dir: ${project_dir}"
|
||||
|
||||
mkdir -p ${prefix}
|
||||
|
||||
# List of files/directories to remove at exit; more entries are added below.
|
||||
# This list will be removed even if there's an error. In debug mode, this
|
||||
# cleanup is not performed.
|
||||
exit_rm_list=("${prefix}")
|
||||
exit_distclean=
|
||||
trap 'at_exit' EXIT HUP INT QUIT ABRT KILL PIPE TERM XCPU
|
||||
|
||||
# Prefix tree:
|
||||
# <prefix>
|
||||
# ├── spack
|
||||
# ├── spack_env
|
||||
# └── spack-user-cache
|
||||
|
||||
spack_cmd="${prefix}/spack/bin/spack"
|
||||
spack_env_path="${prefix}/spack_env"
|
||||
command -v python3 > /dev/null && python_cmd=python3 || python_cmd=python
|
||||
uberenv_cmd="${python_cmd} tests/uberenv/uberenv.py"
|
||||
if [[ ${spack_debug} == true ]]
|
||||
then
|
||||
spack_cmd="${spack_cmd} --debug --stacktrace"
|
||||
uberenv_cmd="${uberenv_cmd} --spack-debug"
|
||||
fi
|
||||
|
||||
# Dependencies
|
||||
if [[ "${mode}" != "--build-only" && "${mode}" != "--test-only" ]]
|
||||
then
|
||||
timed_message "Building dependencies"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "~~~~~ Building Dependencies"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
|
||||
if [[ -z ${spec} ]]
|
||||
then
|
||||
echo "[Error]: SPEC is undefined, aborting..."
|
||||
echo "--spec is mandatory to build dependencies, aborting..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
prefix_opt="--prefix=${prefix}"
|
||||
upstream_opt=""
|
||||
if [[ ${sys_type} != "" ]]
|
||||
then
|
||||
upstream_opt="--upstream=/usr/workspace/mfem/mfem-dependencies/install"
|
||||
fi
|
||||
|
||||
prefix_opt=""
|
||||
|
||||
# Do not run on /dev/shm if only installing dependencies: they will be lost
|
||||
# otherwise.
|
||||
if [[ -d "/dev/shm" && "${mode}" != "--deps-only" ]]
|
||||
then
|
||||
prefix="/dev/shm/${USER}_${CI_PIPELINE_ID:-"NONE"}_${RANDOM}"
|
||||
mkdir -p ${prefix}
|
||||
# clean up ${prefix} at exit:
|
||||
trap 'rm -rf "${prefix}"' EXIT
|
||||
prefix_opt="--prefix=${prefix}"
|
||||
fi
|
||||
echo ${spec} > spec.txt
|
||||
|
||||
# We force Spack to put all generated files (cache and configuration of
|
||||
# all sorts) in a unique location so that there can be no collision
|
||||
# with existing or concurrent Spack.
|
||||
spack_user_cache="${prefix}/spack-user-cache"
|
||||
export SPACK_DISABLE_LOCAL_CONFIG=""
|
||||
export SPACK_USER_CACHE_PATH="${spack_user_cache}"
|
||||
mkdir -p ${spack_user_cache}
|
||||
|
||||
echo "Fetching uberenv ..."
|
||||
# FIXME: the messages from the next clone appear out-of-place, at the end of
|
||||
# the logs on Gitlab. (On Lassen the messages are where expected.)
|
||||
echo "Fetching uberenv."
|
||||
tests/gitlab/get_mfem_uberenv || { echo "Error fetching Uberenv"; exit 1; }
|
||||
|
||||
# Remove "${project_dir}/tests/uberenv" at exit (even if there's an error)
|
||||
exit_rm_list=("${exit_rm_list[@]}" "${project_dir}/tests/uberenv")
|
||||
|
||||
echo "Removing existing configuration"
|
||||
make distclean
|
||||
|
||||
@@ -275,38 +149,10 @@ then
|
||||
config/defaults.mk.new
|
||||
mv -f config/defaults.mk.new config/defaults.mk
|
||||
|
||||
# generate cmake cache file with uberenv and radiuss spack package
|
||||
timed_message "Spack setup and environment"
|
||||
${uberenv_cmd} --setup-and-env-only --spec="${spec}" ${prefix_opt}
|
||||
|
||||
if [[ -n ${ci_registry_token} ]]
|
||||
then
|
||||
timed_message "GitLab registry as Spack Buildcache"
|
||||
${spack_cmd} -D ${spack_env_path} mirror add --unsigned \
|
||||
--oci-username ${ci_registry_user} \
|
||||
--oci-password ${ci_registry_token} \
|
||||
gitlab_ci oci://${ci_registry_image}
|
||||
fi
|
||||
|
||||
timed_message "Spack build of dependencies"
|
||||
${uberenv_cmd} --skip-setup-and-env --spec="${spec}" ${prefix_opt} || \
|
||||
{
|
||||
# Save Spack logs
|
||||
cd ${SPACK_USER_CACHE_PATH}
|
||||
log_archive="${project_dir}/spack-logs-${hostname}-${CI_JOB_ID}.tgz"
|
||||
tar zvcf "${log_archive}" stage/*/*/spack*.txt
|
||||
timed_message "Spack build failed! See log archive: ${log_archive}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ -n ${ci_registry_token} && ${debug_mode} == false ]]
|
||||
then
|
||||
timed_message "Push dependencies to buildcache"
|
||||
${spack_cmd} -D ${spack_env_path} buildcache push \
|
||||
--only dependencies gitlab_ci
|
||||
fi
|
||||
|
||||
timed_message "Dependencies built"
|
||||
echo "Installing dependencies."
|
||||
command -v python > /dev/null && python_cmd=python || python_cmd=python3
|
||||
$python_cmd tests/uberenv/uberenv.py --spec="${spec}" "${upstream_opt}" \
|
||||
"${prefix_opt}"
|
||||
|
||||
# Make sure that a configuration was generated by spack (part 1).
|
||||
cp config/config.mk config/spack-config.mk
|
||||
@@ -324,10 +170,10 @@ then
|
||||
cp config/spack-config.mk config/config.mk
|
||||
cp config/spack_config.hpp config/_config.hpp
|
||||
else
|
||||
echo "[Error]: No result for at least one of"
|
||||
echo "[Error]: ${project_dir}/config/spack-config.mk"
|
||||
echo "[Error]: ${project_dir}/config/spack_config.hpp"
|
||||
echo "[Error]: Spack generated configuration not found."
|
||||
echo "No result for at least one of"
|
||||
echo " ${project_dir}/config/spack-config.mk"
|
||||
echo " ${project_dir}/config/spack_config.hpp"
|
||||
echo "ERROR: Spack generated configuration not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -342,10 +188,10 @@ then
|
||||
# project parent dir.
|
||||
if [[ -e "../data" ]]; then
|
||||
if [[ -L "../data" ]]; then
|
||||
echo "[Information]: '../data' link already exists. Deleting."
|
||||
echo "'../data' link already exists. Deleting."
|
||||
rm "../data"
|
||||
else
|
||||
echo "[Error]: '../data' already exists and it's NOT a link"
|
||||
echo "Error: '../data' already exists and it's NOT a link"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
@@ -358,7 +204,7 @@ then
|
||||
|
||||
if [[ "$with_data" == "true" && ! -d "../data" ]]
|
||||
then
|
||||
echo "[Error]: '$data_dir' is not a directory while asking for --data"
|
||||
echo "ERROR: '$data_dir' is not a directory while asking for --data"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
@@ -370,45 +216,42 @@ then
|
||||
echo "~ Project Dir: ${project_dir}"
|
||||
echo "~ Data Dir: ${data_dir}"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo ""
|
||||
|
||||
timed_message "MFEM Configuration"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "~~~~~ MFEM configuration"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
|
||||
make info
|
||||
|
||||
timed_message "Building MFEM"
|
||||
|
||||
# If the build is terminated, e.g. job timeout, run 'make distclean'
|
||||
exit_distclean=1
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "~~~~~ Building MFEM"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
|
||||
make all -j ${threads}
|
||||
|
||||
exit_distclean=
|
||||
fi
|
||||
|
||||
# Test
|
||||
if [[ "${mode}" != "--deps-only" && "${mode}" != "--build-only" ]]
|
||||
then
|
||||
timed_message "Testing MFEM"
|
||||
|
||||
# If the build is terminated, e.g. job timeout, run 'make distclean'
|
||||
exit_distclean=1
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "~~~~~ Testing MFEM"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
|
||||
make test
|
||||
test_status=$?
|
||||
|
||||
timed_message "Cleaning MFEM"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "~~~~~ Cleaning MFEM"
|
||||
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
|
||||
if make distclean > distclean.log 2>&1; then
|
||||
echo "[Information]: make distclean OK"
|
||||
echo "[make distclean]: OK"
|
||||
else
|
||||
cat distclean.log
|
||||
echo
|
||||
echo "[Information]: make distclean FAILED (see above)"
|
||||
echo "[make distclean]: FAILED (see above)"
|
||||
fi
|
||||
rm -f distclean.log
|
||||
|
||||
exit_distclean=
|
||||
|
||||
exit $test_status
|
||||
fi
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
function info_msg ()
|
||||
{
|
||||
echo "[Information:] ${1}"
|
||||
}
|
||||
|
||||
function error_msg ()
|
||||
{
|
||||
echo "[Error:] ${1}"
|
||||
}
|
||||
|
||||
# Perform a clone while holding a lock file to prevent concurrency on
|
||||
# the destination.
|
||||
# Usage:
|
||||
# locked_clone <repository_url> <destination_dir>
|
||||
function locked_clone ()
|
||||
{
|
||||
if ! command -v flock
|
||||
then
|
||||
error_msg "Required command 'flock' not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
info_msg "Will clone ${1} into ${2}"
|
||||
|
||||
( date; info_msg "Waiting to acquire lock on '${PWD}/${2}.lock' ..."
|
||||
# try to get an exclusive lock on fd 9 (mfem-data.lock) repeating the
|
||||
# try every 5 seconds; we may want to add a counter for the number of
|
||||
# retries to interrupt a potential infinite loop
|
||||
while ! flock -n 9; do sleep 5; done
|
||||
date; info_msg "Acquired lock on '${PWD}/${2}.lock'"
|
||||
# clone/update the autotest repo while holding the file lock on
|
||||
# 'autotest.lock'
|
||||
err=0
|
||||
if [[ ! -d "${2}" ]]; then
|
||||
git clone ${1} ${2}
|
||||
else
|
||||
cd ${2} && git pull && cd ..
|
||||
fi || err=1
|
||||
# sleep for a period to allow NFS to propagate the above changes;
|
||||
# clearly, there is no guarantee that other NFS clients will see the
|
||||
# changes even after the timeout
|
||||
sleep 10
|
||||
exit $err
|
||||
) 9> ${2}.lock
|
||||
}
|
||||
|
||||
# Setup MFEM_DATA_DIR=${SHARED_REPOS_DIR}/mfem-data, see '.gitlab-ci.yml'
|
||||
info_msg "MFEM_DATA_REPO is ${MFEM_DATA_REPO}"
|
||||
info_msg "SHARED_REPOS_DIR is ${SHARED_REPOS_DIR}"
|
||||
|
||||
mkdir -p ${SHARED_REPOS_DIR} && cd ${SHARED_REPOS_DIR}
|
||||
locked_clone ${MFEM_DATA_REPO} mfem-data
|
||||
|
||||
# Setup ${AUTOTEST_ROOT}/autotest:
|
||||
info_msg "AUTOTEST_REPO is ${AUTOTEST_REPO}"
|
||||
info_msg "AUTOTEST_ROOT is ${AUTOTEST_ROOT}"
|
||||
|
||||
mkdir -p ${AUTOTEST_ROOT} && cd ${AUTOTEST_ROOT}
|
||||
locked_clone ${AUTOTEST_REPO} autotest
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# This script is meant be launched in the root directory of MFEM to compile all
|
||||
# the dependencies of MFEM for all the specs in CI. By doing so, we obtain a
|
||||
# Spack instance that can be used as an upstream.
|
||||
# Note: needs mfem-uberenv in MFEM repo (run tests/gitlab/get_mfem_uberenv)
|
||||
|
||||
# This patch applies shared permissions to Spack installations.
|
||||
cd tests/uberenv
|
||||
git apply upstream-permission.patch
|
||||
cd -
|
||||
|
||||
# Get the hostname
|
||||
hostid=${HOSTNAME//[[:digit:]]/}
|
||||
|
||||
# call uberenv for all specs in CI
|
||||
git grep -e "^[^#]" .gitlab/$hostid* | grep "SPEC" \
|
||||
| cut -d' ' -f6- \
|
||||
| sed 's/"//g' \
|
||||
| while read -r line; do
|
||||
python ./tests/uberenv/uberenv.py --spec="$line"
|
||||
done
|
||||
|
||||
# We revert the patch to leave the repo as found.
|
||||
cd tests/uberenv
|
||||
git apply -R upstream-permission.patch
|
||||
cd -
|
||||
@@ -18,7 +18,7 @@ set -o errexit
|
||||
set -o nounset
|
||||
|
||||
uberenv_url="https://github.com/mfem/mfem-uberenv.git"
|
||||
uberenv_ref="a9bd720f83cf1f8afa26b4e69737fcd4a6d462f9"
|
||||
uberenv_ref="fe5fa88876b29ff03177d44a5bd3e09c84ccdcbf"
|
||||
|
||||
[[ ! -d tests/uberenv ]] && git clone ${uberenv_url} tests/uberenv
|
||||
cd tests/uberenv
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
|
||||
FIXME: this file needs to be updated
|
||||
|
||||
# HowTo: Reproduce CI jobs interactively.
|
||||
|
||||
We rely on Spack, driven by uberenv, to build MFEM dependencies automatically
|
||||
@@ -29,48 +26,6 @@ Those modes are essentially the same, but we emphasize building the
|
||||
dependencies as a first isolated step because it makes it clear what is
|
||||
happening and how to use this workflow.
|
||||
|
||||
## Shortcut:
|
||||
|
||||
To help developers reproduce jobs from the CI, a reproducer script is printed
|
||||
in each job that will allow for fast and accurate reproduction of the same
|
||||
scenario as in the CI job. Below is an example extracted for a CI job log:
|
||||
|
||||
```bash
|
||||
working_dir="/usr/workspace/${USER}/mfem/2405156-$(date +%s)"
|
||||
mkdir -p ${working_dir} && cd ${working_dir}
|
||||
git clone https://github.com/MFEM/mfem.git --single-branch --depth=1
|
||||
cd mfem
|
||||
git fetch origin --depth=1 4868222660f03e15ebf7a6daca90800b64baf69d
|
||||
git checkout 4868222660f03e15ebf7a6daca90800b64baf69d
|
||||
git submodule update --init --recursive
|
||||
|
||||
# Variables
|
||||
export SPEC="%gcc@8.3.1 +mpi +cuda cuda_arch=70"
|
||||
|
||||
# Directories
|
||||
export BUILD_ROOT="${working_dir}"
|
||||
export SHARED_REPOS_DIR="${BUILD_ROOT}/.."
|
||||
export MFEM_DATA_DIR="${SHARED_REPOS_DIR}/mfem-data"
|
||||
|
||||
# Repositories
|
||||
export TPLS_REPO="ssh://git@mybitbucket.llnl.gov:7999/mfem/tpls.git"
|
||||
export TESTS_REPO="ssh://git@mybitbucket.llnl.gov:7999/mfem/tests.git"
|
||||
export AUTOTEST_REPO="ssh://git@mybitbucket.llnl.gov:7999/mfem/autotest.git"
|
||||
export MFEM_DATA_REPO="https://github.com/mfem/data.git"
|
||||
|
||||
# Setup directories
|
||||
./tests/gitlab/build_and_test_setup
|
||||
|
||||
# Using the CI build cache is optional and requires a token. Set it like so:
|
||||
# export REGISTRY_TOKEN="<your token here>"
|
||||
|
||||
lalloc 1 -W 45 -q pci --atsdisable tests/gitlab/build_and_test --spec "%gcc@8.3.1 +mpi +cuda cuda_arch=70" --data-dir "/usr/workspace/mfem/gitlab-runner/bernede1/repos/mfem-data" --data
|
||||
```
|
||||
|
||||
**NOTE**
|
||||
|
||||
The REGISTRY_TOKEN can be set using a GitLab Personal Access Token (PAT) with read access to gitlab container registry. This allows to speed up the local builds by fetching the dependencies library instead of building them.
|
||||
|
||||
## Prerequisite: Retrieve Uberenv
|
||||
|
||||
```bash
|
||||
@@ -133,11 +88,6 @@ but still ready to use.
|
||||
|
||||
## Build and test MFEM
|
||||
|
||||
**NOTE**
|
||||
|
||||
If you need mfem data and/or the autotest repo, you may clone them next to your
|
||||
mfem repository.
|
||||
|
||||
### Option 1: Without using scripts
|
||||
|
||||
```bash
|
||||
|
||||
@@ -89,7 +89,7 @@ The currently available test scripts are:
|
||||
- gitignore: Checks for compliance with MFEM's .gitignore rules
|
||||
|
||||
- branch-history: Checks if the current branch history (the commits that will be
|
||||
merged in master) contains unusually large files, unusually large number of
|
||||
merged in main) contains unusually large files, unusually large number of
|
||||
changes in a commit, unusually large number of commits, etc.
|
||||
|
||||
Adding new test scripts is easy and we welcome contributions from users and
|
||||
|
||||
@@ -27,7 +27,7 @@ sub usage {
|
||||
-h|--help prints this usage information and exits
|
||||
|
||||
This script checks if the current branch history, defined as the commits that
|
||||
will be merged in master (those shown in a GitHub PR), contains unusually
|
||||
will be merged in main (those shown in a GitHub PR), contains unusually
|
||||
large files, unusually large number of changes in a commit, unusually large
|
||||
number of commits, etc.
|
||||
|
||||
@@ -72,7 +72,7 @@ my $max_branch_kb = 1000;
|
||||
my $status = 0; # Return code
|
||||
|
||||
# Get SHA hash of all commits in this branch
|
||||
my @commits = split /\n/, `git log --pretty=format:%H master..$branch`;
|
||||
my @commits = split /\n/, `git log --pretty=format:%H main..$branch`;
|
||||
|
||||
# Check if total number of commits in this branch exceeds the maximum allowable
|
||||
my $ncommits = scalar @commits;
|
||||
|
||||
Reference in New Issue
Block a user