diff --git a/.Rbuildignore b/.Rbuildignore
index b7364c9..3f92db2 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -4,3 +4,4 @@
^_pkgdown\.yml$
^docs$
^pkgdown$
+^cran-comments\.md$
diff --git a/.github/workflows/rhub.yaml b/.github/workflows/rhub.yaml
new file mode 100644
index 0000000..74ec7b0
--- /dev/null
+++ b/.github/workflows/rhub.yaml
@@ -0,0 +1,95 @@
+# R-hub's generic GitHub Actions workflow file. It's canonical location is at
+# https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml
+# You can update this file to a newer version using the rhub2 package:
+#
+# rhub::rhub_setup()
+#
+# It is unlikely that you need to modify this file manually.
+
+name: R-hub
+run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}"
+
+on:
+ workflow_dispatch:
+ inputs:
+ config:
+ description: 'A comma separated list of R-hub platforms to use.'
+ type: string
+ default: 'linux,windows,macos'
+ name:
+ description: 'Run name. You can leave this empty now.'
+ type: string
+ id:
+ description: 'Unique ID. You can leave this empty now.'
+ type: string
+
+jobs:
+
+ setup:
+ runs-on: ubuntu-latest
+ outputs:
+ containers: ${{ steps.rhub-setup.outputs.containers }}
+ platforms: ${{ steps.rhub-setup.outputs.platforms }}
+
+ steps:
+ # NO NEED TO CHECKOUT HERE
+ - uses: r-hub/actions/setup@v1
+ with:
+ config: ${{ github.event.inputs.config }}
+ id: rhub-setup
+
+ linux-containers:
+ needs: setup
+ if: ${{ needs.setup.outputs.containers != '[]' }}
+ runs-on: ubuntu-latest
+ name: ${{ matrix.config.label }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config: ${{ fromJson(needs.setup.outputs.containers) }}
+ container:
+ image: ${{ matrix.config.container }}
+
+ steps:
+ - uses: r-hub/actions/checkout@v1
+ - uses: r-hub/actions/platform-info@v1
+ with:
+ token: ${{ secrets.RHUB_TOKEN }}
+ job-config: ${{ matrix.config.job-config }}
+ - uses: r-hub/actions/setup-deps@v1
+ with:
+ token: ${{ secrets.RHUB_TOKEN }}
+ job-config: ${{ matrix.config.job-config }}
+ - uses: r-hub/actions/run-check@v1
+ with:
+ token: ${{ secrets.RHUB_TOKEN }}
+ job-config: ${{ matrix.config.job-config }}
+
+ other-platforms:
+ needs: setup
+ if: ${{ needs.setup.outputs.platforms != '[]' }}
+ runs-on: ${{ matrix.config.os }}
+ name: ${{ matrix.config.label }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config: ${{ fromJson(needs.setup.outputs.platforms) }}
+
+ steps:
+ - uses: r-hub/actions/checkout@v1
+ - uses: r-hub/actions/setup-r@v1
+ with:
+ job-config: ${{ matrix.config.job-config }}
+ token: ${{ secrets.RHUB_TOKEN }}
+ - uses: r-hub/actions/platform-info@v1
+ with:
+ token: ${{ secrets.RHUB_TOKEN }}
+ job-config: ${{ matrix.config.job-config }}
+ - uses: r-hub/actions/setup-deps@v1
+ with:
+ job-config: ${{ matrix.config.job-config }}
+ token: ${{ secrets.RHUB_TOKEN }}
+ - uses: r-hub/actions/run-check@v1
+ with:
+ job-config: ${{ matrix.config.job-config }}
+ token: ${{ secrets.RHUB_TOKEN }}
diff --git a/DESCRIPTION b/DESCRIPTION
index e1b2677..697e77c 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Package: coupling
-Title: Coupling Coordination Analysis
-Version: 0.0.0.9000
+Title: Analysis of Coupling Coordination Degree
+Version: 0.1
Authors@R:
person(given = "Wenbo", family = "Lyu",
email = "lyu.geosocial@gmail.com",
@@ -17,7 +17,10 @@ LinkingTo:
Rcpp,
RcppThread
Suggests:
+ infoxtr,
+ pc,
Rcpp,
RcppThread,
+ spEDM
Config/roxygen2/markdown: TRUE
Config/roxygen2/version: 8.0.0
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..33ebd9b
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,3 @@
+# coupling 0.1
+
+* Initial CRAN submission.
diff --git a/README.md b/README.md
index 92357a5..953b9b0 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
-***Coupling** Coordination Analysis*
+*Analysis of Coupling Coordination Degree*
*coupling* is an R package for coupling coordination analysis based on coupling coordination degree (CCD) models. It incorporates metacoupling frameworks to characterize cross-scale linkages, flows, and feedbacks within and among coupled systems.
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 36d1273..15cd5bd 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -18,7 +18,7 @@ navbar:
home:
title: |
- ccd | Coupling Coordination Analysis
+ coupling | Analysis of Coupling Coordination Degree
authors:
Wenbo Lyu:
href: https://spatlyu.github.io/
diff --git a/cran-comments.md b/cran-comments.md
new file mode 100644
index 0000000..858617d
--- /dev/null
+++ b/cran-comments.md
@@ -0,0 +1,5 @@
+## R CMD check results
+
+0 errors | 0 warnings | 1 note
+
+* This is a new release.
diff --git a/inst/CITATION b/inst/CITATION
new file mode 100644
index 0000000..f553ffb
--- /dev/null
+++ b/inst/CITATION
@@ -0,0 +1,10 @@
+citHeader("To cite package coupling in publications, please use:")
+
+bibentry(
+ bibtype = "Manual",
+ title = "{coupling: Analysis of Coupling Coordination Degree}",
+ author = "Wenbo Lyu",
+ year = "2026",
+ note = "R package version 0.1",
+ doi = "10.32614/CRAN.package.coupling"
+)
diff --git a/inst/include/coupling/ccd.hpp b/inst/include/coupling/ccd.hpp
index d978cb8..d2c18ac 100644
--- a/inst/include/coupling/ccd.hpp
+++ b/inst/include/coupling/ccd.hpp
@@ -295,6 +295,10 @@ inline std::vector ccd_c(
if (n_units == 0) return {};
std::vector result(n_units, 0.0);
+
+ if (threads == 0) threads = 1;
+ size_t hw = std::thread::hardware_concurrency();
+ if (hw > 0) threads = std::min(threads, hw);
if (threads <= 1) {
for (size_t i = 0; i < n_units; ++i) {
diff --git a/inst/include/coupling/metacoupling.hpp b/inst/include/coupling/metacoupling.hpp
index 5e0b639..a409503 100644
--- a/inst/include/coupling/metacoupling.hpp
+++ b/inst/include/coupling/metacoupling.hpp
@@ -312,6 +312,13 @@ inline std::vector> metacoupling_c(
result[1][s] = peri_sum;
result[2][s] = tele_sum;
};
+
+ // ============================================================
+ // Check for available threads
+ // ============================================================
+ if (threads == 0) threads = 1;
+ size_t hw = std::thread::hardware_concurrency();
+ if (hw > 0) threads = std::min(threads, hw);
// ============================================================
// Parallel or serial execution
@@ -357,6 +364,13 @@ inline std::vector> metacoupling(
size_t full_perm = 1ULL << p;
+ // ============================================================
+ // Check for available threads
+ // ============================================================
+ if (threads == 0) threads = 1;
+ size_t hw = std::thread::hardware_concurrency();
+ if (hw > 0) threads = std::min(threads, hw);
+
// ============================================================
// Step 1: reuse existing C computation
// ============================================================
@@ -399,11 +413,7 @@ inline std::vector> metacoupling(
return sum_t / static_cast(count);
};
- // ============================================================
- // Step 3: assemble results
- // ============================================================
- for (size_t s = 0; s < n_units; ++s) {
-
+ auto worker4D = [&](size_t s) {
// ---- intra ----
double C_intra = C_res[0][s];
double T_intra = compute_T_intra(s);
@@ -442,6 +452,17 @@ inline std::vector> metacoupling(
result[4][s] = C_tele;
result[5][s] = std::sqrt(C_tele * tele_T_sum);
+ };
+
+ // ============================================================
+ // Step 3: assemble results
+ // ============================================================
+ if (threads <= 1) {
+ for (size_t s = 0; s < n_units; ++s) {
+ worker4D(s);
+ }
+ } else {
+ RcppThread::parallelFor(0, n_units, worker4D, threads);
}
return result;