conspire/domain/partition/feti/dual_primal/
mod.rs1pub(crate) mod coarse;
2pub(crate) mod condense;
3pub(crate) mod corner;
4pub(crate) mod rigid;
5pub(crate) mod rigid_projector;
6#[cfg(test)]
7mod test;
8
9use crate::geometry::mesh::Partition;
10use std::collections::HashSet;
11
12pub(crate) use corner::{CornerDofs, CornerSelection};
13
14pub struct BoundaryConditions {
23 fixed: HashSet<(usize, usize)>,
24}
25
26impl BoundaryConditions {
27 pub fn new(fixed: Vec<(usize, usize)>) -> Self {
28 Self {
29 fixed: fixed.into_iter().collect(),
30 }
31 }
32 pub fn none() -> Self {
33 Self {
34 fixed: HashSet::new(),
35 }
36 }
37 fn is_fixed(&self, node: usize, component: usize) -> bool {
38 self.fixed.contains(&(node, component))
39 }
40}
41
42pub(crate) struct DualPrimalSplit {
49 primal: Vec<usize>,
50 primal_global: Vec<usize>,
51 dual: Vec<usize>,
52}
53
54impl DualPrimalSplit {
55 #[cfg(test)]
56 pub(crate) fn new(primal: Vec<usize>, dual: Vec<usize>) -> Self {
57 let primal_global = primal.clone();
58 Self {
59 primal,
60 primal_global,
61 dual,
62 }
63 }
64 fn from_subdomain_nodes(
65 subdomain_nodes: &[usize],
66 corner_dofs: &CornerDofs,
67 boundary_conditions: &BoundaryConditions,
68 dimension: usize,
69 ) -> Self {
70 let mut primal = Vec::new();
71 let mut primal_global = Vec::new();
72 let mut dual = Vec::new();
73 subdomain_nodes
74 .iter()
75 .enumerate()
76 .for_each(|(local, &node)| {
77 (0..dimension).for_each(|component| {
78 if boundary_conditions.is_fixed(node, component) {
79 return;
80 }
81 let dof = dimension * local + component;
82 if let Some(global) = corner_dofs.global_index(node, component) {
83 primal.push(dof);
84 primal_global.push(global);
85 } else {
86 dual.push(dof);
87 }
88 })
89 });
90 Self {
91 primal,
92 primal_global,
93 dual,
94 }
95 }
96 pub(crate) fn primal(&self) -> &[usize] {
97 &self.primal
98 }
99 pub(crate) fn primal_global(&self) -> &[usize] {
100 &self.primal_global
101 }
102 pub(crate) fn dual(&self) -> &[usize] {
103 &self.dual
104 }
105}
106
107pub(crate) fn build_splits(
108 partition: &Partition,
109 corners: &CornerSelection,
110 boundary_conditions: &BoundaryConditions,
111 dimension: usize,
112) -> (Vec<DualPrimalSplit>, CornerDofs) {
113 let corner_dofs = CornerDofs::new(corners, boundary_conditions, dimension);
114 let splits = partition
115 .parts_nodes()
116 .iter()
117 .map(|nodes| {
118 DualPrimalSplit::from_subdomain_nodes(
119 nodes,
120 &corner_dofs,
121 boundary_conditions,
122 dimension,
123 )
124 })
125 .collect();
126 (splits, corner_dofs)
127}