Skip to content

Conversation

@jowezarek
Copy link
Contributor

@jowezarek jowezarek commented Oct 30, 2025

We implement the class DirichletProjector and MultipatchDirichletProjector and include tests.

DirichletProjector

is a subclass of LinearOperator. Projects coefficients of functions belonging to a fem_space of space_kind $\in$ {"h1", "hcurl", "hdiv", "l2"} to coefficients of functions satisfying the corresponding homogeneous Dirichlet boundary conditions. These projectors respect periodicity, i.e., coefficients corresponding to "periodic boundaries" will not be changed.

Take for example the constant function $f(x, y) = 1$ on an Annulus.

P0, _, _ = derham_h.projectors()
f        = lambda x, y : 1
F        = P0(f)
plot_field_2d(fem_field=F, domain=domain, N_vis=100, cmap='plasma')
F

Applying the DirichletProjector sets correctly only the DOFs to 0 that belong to basis functions that are different from 0 on the "x1-direction-boundary".

DP0, _ = derham_h.dirichlet_projectors(kind='linop')
F_dp   = FemField(derham_h.V0, DP0 @ F.coeffs)
plot_field_2d(fem_field=F_dp, domain=domain, N_vis=100, cmap='plasma')
F_dbp

Note: Low resolution! ncells = [3, 3]; degree = [1, 1]

Usage

Obtain these projectors in the FEEC context directly from a DiscreteDeRham object

# in 1D
DP0, DP1 = derham_h.dirichlet_projectors(kind='linop')

# in 2D
DP0, DP1, DP2 = derham_h.dirichlet_projectors(kind='linop')

# in 3D
DP0, DP1, DP2, DP3 = derham_h.dirichlet_projectors(kind='linop')

The last projector is simply an IdentityOperator.

When instead working with FEM objects only:

from psydac.fem.projectors import DirichletProjector

# working with a space that has a kind
V   = ScalarFunctionSpace('V', domain, kind='h1')
Vh  = discretize(V, domain_h, degree=degree)
DP  = DirichletProjector(Vh)

# working with a space that has no kind
V   = VectorFunctionSpace('V', domain)
Vh  = discretize(V, domain_h, degree=degree)
DP  = DirichletProjector(Vh, kind='hcurl') # or 'hdiv'

Similarity with conforming_projectors

Identical to derham_h.conforming_projectors(kind='linop', hom_bc=True) on a single-patch.
On multi-patch domains, derham_h.conforming_projectors also affect the solution at the interfaces between patches, as required by the broken-FEEC theory. If required, they have the additional ability to preserve moments of the solution.
Unfortunately, the conforming projectors are only implemented in 2D.

@codacy-production
Copy link

codacy-production bot commented Oct 30, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for b6d4d5d1 78.54%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (b6d4d5d) Report Missing Report Missing Report Missing
Head commit (f35d98e) 63696 39488 61.99%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#536) 205 161 78.54%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

@jowezarek jowezarek marked this pull request as ready for review October 30, 2025 15:20
@jowezarek jowezarek requested a review from yguclu October 30, 2025 15:20
@yguclu
Copy link
Member

yguclu commented Oct 30, 2025

Good job @jowezarek! I will look into the details shortly.

@FrederikSchnack: How much work do you think is needed to extend this PR to multi-patch domains?

@FrederikSchnack
Copy link
Contributor

Good catch! The conforming projectors are not very well tested on single-patch domains. Since the single-patch geometry behaves fundamentally different than in the multi-patch setting, at least when it comes to boundaries, we did not check if the periodicity is enforced by the FEM spaces. There is a very easy fix to this, should I push it to this pull-request?

@FrederikSchnack
Copy link
Contributor

I think the extension to multi-patch should not be too difficult, the question is if/ for what this is needed? As I see it, this PR is mainly used for the 3D cases, where we don't have conforming projections (w/ BC) at hand.

Everything else in 2D can be done by conforming projections and other multi-patch examples like a Nitsche method enforce the BC weakly.

@jowezarek jowezarek mentioned this pull request Oct 31, 2025
Copy link
Contributor

@FrederikSchnack FrederikSchnack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My main remark is to integrate the DBP a little better into the feec-api, otherwise the additions look good to me.

@yguclu
Copy link
Member

yguclu commented Nov 3, 2025

@FrederikSchnack On the topic of API consistency between the Dirichlet boundary projectors and the conforming projectors... I have just noticed that the boolean parameter mom_pres is not documented in the docstrings of

  • DiscreteDeRham.conforming_projectors
  • ConformingProjectionV0
  • ConformingProjectionV1

If this is an important parameter, I think it should be included in the docstrings. Or maybe it could be skipped altogether given that the parameter p_moments should contain sufficient information?

Copy link
Member

@yguclu yguclu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job!

I have a few comments, mostly on the unit tests.
Further, I would like to see some tests run in parallel, could this be done?

@FrederikSchnack
Copy link
Contributor

@FrederikSchnack On the topic of API consistency between the Dirichlet boundary projectors and the conforming projectors... I have just noticed that the boolean parameter mom_pres is not documented in the docstrings of

If this is an important parameter, I think it should be included in the docstrings. Or maybe it could be skipped altogether given that the parameter p_moments should contain sufficient information?

Good catch! The parameter mom_pres was introduced for simplicity to set the projectors to the maximal order of moment preservation. This is probably the parameter a user should set, so I think we should document it in the doc strings.

Together with your other comments on the conforming projections, should we do the changes here or as a separate PR?

@yguclu
Copy link
Member

yguclu commented Nov 3, 2025

@FrederikSchnack On the topic of API consistency between the Dirichlet boundary projectors and the conforming projectors... I have just noticed that the boolean parameter mom_pres is not documented in the docstrings of

If this is an important parameter, I think it should be included in the docstrings. Or maybe it could be skipped altogether given that the parameter p_moments should contain sufficient information?

Good catch! The parameter mom_pres was introduced for simplicity to set the projectors to the maximal order of moment preservation. This is probably the parameter a user should set, so I think we should document it in the doc strings.

Together with your other comments on the conforming projections, should we do the changes here or as a separate PR?

This should be a small change, so we could include it here directly

@codacy-production
Copy link

codacy-production bot commented Nov 3, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.06% 65.38%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (c7ca428) 31653 19575 61.84%
Head commit (424f2d5) 63694 (+32041) 39428 (+19853) 61.90% (+0.06%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#536) 208 136 65.38%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Copy link
Member

@yguclu yguclu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes! I have some other remarks

Copy link
Member

@yguclu yguclu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing (most of) my comments! I have a few more 😄

@yguclu yguclu added Next Release Must be in next release urgent PR should be merged ASAP labels Nov 5, 2025
@jowezarek jowezarek requested a review from yguclu November 7, 2025 11:01
@yguclu
Copy link
Member

yguclu commented Nov 10, 2025

Good job for addressing my comments!

The one (important) thing which is still missing is parallel tests. I asked this in a previous review last week 😉

@jowezarek
Copy link
Contributor Author

Good job for addressing my comments!

The one (important) thing which is still missing is parallel tests. I asked this in a previous review last week 😉

Out of the three new tests

@pytest.mark.parametrize('dim', [1, 2, 3])
def test_function_space_boundary_projector(dim)

@pytest.mark.parametrize('dim', [1, 2, 3])
def test_discrete_derham_boundary_projector_parallel(dim)

def test_discrete_derham_boundary_projector_multipatch()

the first two are rather slow (in particular the 3D parts).
I propose the following change: Let's perform the first test for dims 1 & 2, and the second in parallel for dims 1 & 3.

@pytest.mark.parametrize('dim', [1, 2])
def test_function_space_boundary_projector(dim)

@pytest.mark.parametrize('dim', [1, 3])
@pytest.mark.parallel
def test_discrete_derham_boundary_projector_parallel(dim) # here now passing comm=MPI.COMM_WORLD instead of None

def test_discrete_derham_boundary_projector_multipatch()

This way, we still test all dimensions, the tests run faster, and we have a parallel test. What do you think @yguclu ?

Copy link
Member

@yguclu yguclu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are my last comments!

@jowezarek jowezarek requested a review from yguclu November 21, 2025 13:40
@jowezarek jowezarek requested a review from yguclu November 21, 2025 15:34
Copy link
Member

@yguclu yguclu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Good job!

@yguclu yguclu merged commit 1e6a114 into devel Nov 21, 2025
10 checks passed
@yguclu yguclu deleted the dirichlet branch November 21, 2025 17:25
campospinto pushed a commit that referenced this pull request Dec 12, 2025
We implement the class `DirichletProjector` and
`MultipatchDirichletProjector` and include tests.

DirichletProjector
---------------------------
is a subclass of `LinearOperator`. Projects coefficients of functions
belonging to a `fem_space` of `space_kind` $\in$ `{"h1", "hcurl",
"hdiv", "l2"}` to coefficients of functions satisfying the corresponding
homogeneous Dirichlet boundary conditions. These projectors **respect
periodicity**, i.e., coefficients corresponding to "periodic boundaries"
**will not be changed**.

Take for example the constant function $f(x, y) = 1$ on an Annulus.
```python
P0, _, _ = derham_h.projectors()
f        = lambda x, y : 1
F        = P0(f)
plot_field_2d(fem_field=F, domain=domain, N_vis=100, cmap='plasma')
```
See [image](https://github.com/user-attachments/assets/83dc42c6-5ecc-46ae-a0a0-6ceae85526fe).

Applying the `DirichletProjector` sets correctly only the DOFs to 0 that
belong to basis functions that are different from 0 on the
"x1-direction-boundary".

```python
DP0, _ = derham_h.dirichlet_projectors(kind='linop')
F_dp   = FemField(derham_h.V0, DP0 @ F.coeffs)
plot_field_2d(fem_field=F_dp, domain=domain, N_vis=100, cmap='plasma')
```
See [image](https://github.com/user-attachments/assets/a117c5c6-8379-4bcf-b8a8-71e59d2d0eeb).

Usage
---------
Obtain these projectors in the **FEEC context** directly from a
`DiscreteDeRham` object
```python
DP0, DP1 = derham_h.dirichlet_projectors(kind='linop') # in 1D
DP0, DP1, DP2 = derham_h.dirichlet_projectors(kind='linop') # in 2D
DP0, DP1, DP2, DP3 = derham_h.dirichlet_projectors(kind='linop') # in 3D
```
The last projector is simply an `IdentityOperator`.

When instead working with **FEM** objects only: 
```python
from psydac.fem.projectors import DirichletProjector

# working with a space that has a kind
V   = ScalarFunctionSpace('V', domain, kind='h1')
Vh  = discretize(V, domain_h, degree=degree)
DP  = DirichletProjector(Vh)

# working with a space that has no kind
V   = VectorFunctionSpace('V', domain)
Vh  = discretize(V, domain_h, degree=degree)
DP  = DirichletProjector(Vh, kind='hcurl') # or 'hdiv'
```

Similarity with `conforming_projectors`
--------------------------------------------------------
Identical to `derham_h.conforming_projectors(kind='linop', hom_bc=True)`
**on a single-patch**.
On **multi-patch** domains, `derham_h.conforming_projectors` also affect
the solution at the **interfaces** between patches, as required by the
broken-FEEC theory. If required, they have the additional ability to
preserve moments of the solution.
Unfortunately, the conforming projectors are only implemented in 2D.

---------

Co-authored-by: Frederik Schnack <frederik.schnack@ipp.mpg.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Next Release Must be in next release urgent PR should be merged ASAP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants