use crate::algs::communicator::{CommTag, Communicator, SectionCommTags};
use crate::algs::completion::section_completion::complete_section_with_tags_and_ownership;
use crate::data::constrained_section::{ConstraintSet, apply_constraints_to_section};
use crate::data::hanging_node_constraints::{
HangingNodeConstraints, apply_hanging_constraints_to_section,
};
use crate::data::section::Section;
use crate::data::storage::Storage;
use crate::mesh_error::MeshSieveError;
use crate::overlap::delta::{CopyDelta, ValueDelta};
use crate::overlap::overlap::Overlap;
use crate::topology::ownership::PointOwnership;
#[derive(Copy, Clone, Debug)]
pub struct AssemblyCommTags {
pub reduce: SectionCommTags,
pub complete: SectionCommTags,
}
impl AssemblyCommTags {
#[inline]
pub const fn from_base(base: CommTag) -> Self {
Self {
reduce: SectionCommTags::from_base(base),
complete: SectionCommTags::from_base(base.offset(2)),
}
}
}
pub fn assemble_section_with_tags_and_ownership<V, S, D, C, Con>(
section: &mut Section<V, S>,
overlap: &Overlap,
ownership: &PointOwnership,
comm: &C,
my_rank: usize,
tags: AssemblyCommTags,
constraints: &Con,
) -> Result<(), MeshSieveError>
where
V: Clone + Default + Send + PartialEq + bytemuck::Pod + Copy + 'static,
S: Storage<V>,
D: ValueDelta<V> + Send + Sync + 'static,
D::Part: bytemuck::Pod + Default + Copy,
C: Communicator + Sync,
Con: ConstraintSet<V>,
{
complete_section_with_tags_and_ownership::<V, S, D, C>(
section,
overlap,
ownership,
comm,
my_rank,
tags.reduce,
)?;
apply_constraints_to_section(section, constraints)?;
complete_section_with_tags_and_ownership::<V, S, CopyDelta, C>(
section,
overlap,
ownership,
comm,
my_rank,
tags.complete,
)?;
Ok(())
}
pub fn assemble_section_with_hanging_constraints_and_ownership<V, S, D, C, Con>(
section: &mut Section<V, S>,
overlap: &Overlap,
ownership: &PointOwnership,
comm: &C,
my_rank: usize,
tags: AssemblyCommTags,
hanging_constraints: &HangingNodeConstraints<V>,
constraints: &Con,
) -> Result<(), MeshSieveError>
where
V: Clone
+ Default
+ Send
+ PartialEq
+ bytemuck::Pod
+ Copy
+ 'static
+ core::ops::AddAssign
+ core::ops::Mul<Output = V>,
S: Storage<V>,
D: ValueDelta<V> + Send + Sync + 'static,
D::Part: bytemuck::Pod + Default + Copy,
C: Communicator + Sync,
Con: ConstraintSet<V>,
{
complete_section_with_tags_and_ownership::<V, S, D, C>(
section,
overlap,
ownership,
comm,
my_rank,
tags.reduce,
)?;
apply_hanging_constraints_to_section(section, hanging_constraints)?;
apply_constraints_to_section(section, constraints)?;
complete_section_with_tags_and_ownership::<V, S, CopyDelta, C>(
section,
overlap,
ownership,
comm,
my_rank,
tags.complete,
)?;
Ok(())
}
pub fn assemble_section_with_ownership<V, S, D, C, Con>(
section: &mut Section<V, S>,
overlap: &Overlap,
ownership: &PointOwnership,
comm: &C,
my_rank: usize,
constraints: &Con,
) -> Result<(), MeshSieveError>
where
V: Clone + Default + Send + PartialEq + bytemuck::Pod + Copy + 'static,
S: Storage<V>,
D: ValueDelta<V> + Send + Sync + 'static,
D::Part: bytemuck::Pod + Default + Copy,
C: Communicator + Sync,
Con: ConstraintSet<V>,
{
let tags = AssemblyCommTags::from_base(CommTag::new(0xBEEF));
assemble_section_with_tags_and_ownership::<V, S, D, C, Con>(
section,
overlap,
ownership,
comm,
my_rank,
tags,
constraints,
)
}
use crate::data::closure::{
ClosureOrder, IdentitySectionSym, SectionSym, build_closure_index,
build_closure_index_unoriented,
};
use crate::data::global_map::LocalToGlobalMap;
use crate::discretization::runtime::{ClosureDof, CsrPattern, DofMap, dof_map_from_closure_index};
use crate::topology::point::PointId;
use crate::topology::sieve::{Orientation, OrientedSieve, Sieve};
use std::collections::{BTreeSet, HashMap};
pub fn cell_closure_dof_map<T, V, Sct>(
topology: &T,
section: &Section<V, Sct>,
cell: PointId,
topology_version: u64,
order: &ClosureOrder,
) -> Result<DofMap, MeshSieveError>
where
T: Sieve<Point = PointId>,
Sct: Storage<V>,
{
let index = build_closure_index_unoriented(
topology,
section,
cell,
topology_version,
order,
&IdentitySectionSym,
)?;
Ok(dof_map_from_closure_index(&index))
}
pub fn oriented_cell_closure_dof_map<T, V, Sct, O, Sym>(
topology: &T,
section: &Section<V, Sct>,
cell: PointId,
topology_version: u64,
order: &ClosureOrder,
sym: &Sym,
) -> Result<DofMap, MeshSieveError>
where
T: OrientedSieve<Point = PointId, Orient = O>,
Sct: Storage<V>,
O: Orientation + Eq + std::hash::Hash,
Sym: SectionSym<O>,
{
let index = build_closure_index(topology, section, cell, topology_version, order, sym)?;
Ok(dof_map_from_closure_index(&index))
}
pub fn preallocation_csr_from_closure<T, V, Sct>(
topology: &T,
section: &Section<V, Sct>,
cells: impl IntoIterator<Item = PointId>,
topology_version: u64,
order: &ClosureOrder,
) -> Result<CsrPattern, MeshSieveError>
where
T: Sieve<Point = PointId>,
Sct: Storage<V>,
{
let mut rows: HashMap<ClosureDof, BTreeSet<ClosureDof>> = HashMap::new();
for cell in cells {
let map = cell_closure_dof_map(topology, section, cell, topology_version, order)?;
let dofs = map.closure_dofs().to_vec();
for row in &dofs {
rows.entry(*row).or_default().extend(dofs.iter().copied());
}
}
Ok(csr_from_rows(rows))
}
pub fn global_preallocation_csr_from_closure<T, V, Sct>(
topology: &T,
section: &Section<V, Sct>,
global_map: &LocalToGlobalMap,
cells: impl IntoIterator<Item = PointId>,
topology_version: u64,
order: &ClosureOrder,
) -> Result<GlobalCsrPattern, MeshSieveError>
where
T: Sieve<Point = PointId>,
Sct: Storage<V>,
{
let local = preallocation_csr_from_closure(topology, section, cells, topology_version, order)?;
let rows = local
.rows
.iter()
.map(|dof| {
global_map
.global_index(dof.point, dof.local_dof)
.map(|g| g as usize)
})
.collect::<Result<Vec<_>, _>>()?;
let adjncy = local
.adjncy
.iter()
.map(|dof| {
global_map
.global_index(dof.point, dof.local_dof)
.map(|g| g as usize)
})
.collect::<Result<Vec<_>, _>>()?;
Ok(GlobalCsrPattern {
xadj: local.xadj,
adjncy,
rows,
})
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GlobalCsrPattern {
pub xadj: Vec<usize>,
pub adjncy: Vec<usize>,
pub rows: Vec<usize>,
}
fn csr_from_rows(mut rows: HashMap<ClosureDof, BTreeSet<ClosureDof>>) -> CsrPattern {
let mut row_dofs: Vec<_> = rows.keys().copied().collect();
row_dofs.sort_unstable();
let mut xadj = Vec::with_capacity(row_dofs.len() + 1);
let mut adjncy = Vec::new();
xadj.push(0);
for row in &row_dofs {
if let Some(cols) = rows.remove(row) {
adjncy.extend(cols);
}
xadj.push(adjncy.len());
}
CsrPattern {
xadj,
adjncy,
rows: row_dofs,
}
}