Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non Matching Multipatch #320

Merged
merged 81 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
d830ae1
add non matching conforming projection operators
FrederikSchnack Jul 14, 2023
a27a062
add some plotting utilities
FrederikSchnack Jul 14, 2023
bbad569
make multipatch examples run
FrederikSchnack Jul 14, 2023
ec10dfd
Use SymPDE development version from GitHub
yguclu Jul 17, 2023
a166d02
allow for non-matching grids in postprocessing
FrederikSchnack Jul 17, 2023
87bbef6
add utils
FrederikSchnack Jul 17, 2023
1a41cd0
adds non-matching domain utilities
FrederikSchnack Jul 18, 2023
e84552a
adds curl-curl test case comparisson
FrederikSchnack Jul 18, 2023
548881a
small changes
FrederikSchnack Jul 24, 2023
b0e64c9
Merge remote-tracking branch 'origin/devel' into non_matching_multipatch
FrederikSchnack Jul 24, 2023
4dbc422
Merge branch 'devel' into non_matching_multipatch
yguclu Jul 25, 2023
b3d1451
add time-domain Maxwell
FrederikSchnack Jul 27, 2023
a806b6d
add time harmonic and time domain maxwell examples
FrederikSchnack Jul 28, 2023
26578f6
add new tests and last example
FrederikSchnack Aug 2, 2023
f68c562
Merge branch 'devel' into non_matching_multipatch
FrederikSchnack Sep 20, 2023
7fbaecf
make Codacy happy
FrederikSchnack Sep 20, 2023
b52041f
add pml example
FrederikSchnack Nov 27, 2023
7f5be32
update non_matching operators and add proposal of tests
FrederikSchnack Nov 27, 2023
1692570
adapt files to new projection
FrederikSchnack Nov 27, 2023
544a237
make codacy happy
FrederikSchnack Nov 28, 2023
7b357bb
add some pml experiments
FrederikSchnack Dec 12, 2023
ebaa9f3
Merge branch 'devel' into non_matching_multipatch
FrederikSchnack Mar 1, 2024
a147990
add docs and readability
FrederikSchnack Mar 5, 2024
c7325da
Merge branch 'devel' into non_matching_multipatch
FrederikSchnack Mar 5, 2024
567ce21
move pml experiments to its own branch
FrederikSchnack Mar 5, 2024
2af29a8
adapt tests
FrederikSchnack Mar 5, 2024
d4fbdbf
change Hodge matrix naming conventions
FrederikSchnack Mar 7, 2024
11a9859
Merge branch 'devel' into non_matching_multipatch
FrederikSchnack Mar 7, 2024
ae90d77
Merge branch 'devel' into non_matching_multipatch
yguclu Mar 19, 2024
05bd083
Merge branch 'devel' into non_matching_multipatch
FrederikSchnack Apr 23, 2024
ff8c1c0
adds revised Hcurl conforming projections and adapts the tests, prior…
FrederikSchnack May 22, 2024
53c1b3c
adapt conforming examples to new projections
FrederikSchnack May 22, 2024
dcc86b1
update non-matching examples
FrederikSchnack May 23, 2024
a853a47
work in comments
FrederikSchnack May 23, 2024
5371468
update tests
FrederikSchnack May 23, 2024
9357bdd
Merge branch 'devel' into non_matching_multipatch
FrederikSchnack May 23, 2024
ba230ba
stop using create_domain() -- wip
campospinto May 31, 2024
685f4a5
use Domain.join() to build non-matching domains
campospinto Jun 2, 2024
a3a5341
using temp function for sympde Domain.join
campospinto Jun 4, 2024
220f1cf
adding ref
campospinto Jun 4, 2024
52fec60
Merge example scripts and get rid of get_source_and_solution_OBSOLETE
FrederikSchnack Jun 10, 2024
4d5f780
clean up multipatch domain utilities
FrederikSchnack Jun 11, 2024
fffe43f
Coarsen test runs and add timedomain dummy run
FrederikSchnack Jun 11, 2024
d417da4
Make codacy happy
FrederikSchnack Jun 12, 2024
a748a4d
fix typo
FrederikSchnack Jun 12, 2024
2bceaf6
Expose multipatch modules to docs
FrederikSchnack Jun 17, 2024
383d341
minor documentation related fixes
jowezarek Jun 17, 2024
a9da50e
sphinx fix
campospinto Jun 18, 2024
7f9b522
functions stencil index to petsc index and viceversa
e-moral-sanchez May 8, 2024
b8bdab9
efficient conversion to PETSc of StencilVectors
e-moral-sanchez May 8, 2024
eba63ff
works for 1D stencil matrix with multiple processes
e-moral-sanchez May 13, 2024
20b7fe7
correct indexing for 2D stencilmatrix
e-moral-sanchez May 15, 2024
f11599d
works 1d,2d,3d stencilmatrix without periodic BC
e-moral-sanchez May 15, 2024
7a2c555
efficient conversion of stencilmatrix to PETSc.Mat for 1,2,3D and pe…
e-moral-sanchez May 16, 2024
4ad477c
Fixed conversion from 2D BlockStencilVector to Petsc.Vec
e-moral-sanchez May 17, 2024
f62385e
fix general case also for stencilvector 2D
e-moral-sanchez May 17, 2024
1256836
fixed petsc_to_psydac for BlockVectors
e-moral-sanchez May 21, 2024
b228eac
PETSc conversion works for StencilVector and BlockStencilVector of 1 …
e-moral-sanchez May 21, 2024
437c38f
conversion works for StencilMatrix
e-moral-sanchez May 21, 2024
80f3e6c
works for BlockLinearOperators, the blocks of which are Stencilmatrices
e-moral-sanchez May 21, 2024
abe2614
Clean up, docstrings
e-moral-sanchez May 21, 2024
21f06dc
fix bugs
e-moral-sanchez May 22, 2024
889619d
sequential case, docstrings
e-moral-sanchez May 22, 2024
ed5abc0
cleaning
e-moral-sanchez May 22, 2024
cddbd38
erase forgotten comments
e-moral-sanchez May 22, 2024
bd2fcd1
fix loop stencil
e-moral-sanchez May 23, 2024
ab228b9
forgotten prints
e-moral-sanchez May 27, 2024
820bd7b
add pyccel kernel
e-moral-sanchez May 29, 2024
3a7c2a7
string for type annotations
e-moral-sanchez May 29, 2024
1778055
clean up plus fix serial case
e-moral-sanchez May 29, 2024
bdc0645
clean time measurements
e-moral-sanchez Jun 3, 2024
a560b90
fix version 12 of macos in tests
e-moral-sanchez Jun 12, 2024
f65b21e
Fixes for CI failures caused by new macOS runner version and numpy 2.0
kvrigor Jun 19, 2024
9172dfc
CI: Temporarily disabled docs deployment since base repo is a fork
kvrigor Jun 19, 2024
45cf90c
Update macos version
e-moral-sanchez Jun 21, 2024
ce4f189
Disable deploy_docs in documentation.yml
FrederikSchnack Jun 21, 2024
6ff11ee
Revert "Disable deploy_docs in documentation.yml"
yguclu Aug 1, 2024
613b077
Revert "CI: Temporarily disabled docs deployment since base repo is a…
yguclu Aug 1, 2024
bc75682
Style cleanup of stencil2IJV_kernels.py
yguclu Jul 31, 2024
8d429c1
Apply some PEP8 recommendations to topetsc.py
yguclu Aug 1, 2024
eaa9854
Merge branch 'devel' into non_matching_multipatch
yguclu Aug 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion psydac/api/fem.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,9 @@ def allocate_matrices(self, backend=None):
elif use_prolongation:
Ps = [knot_insertion_projection_operator(trs, trs.get_refined_space(ncells)) for trs in trial_fem_space.spaces]
P = BlockLinearOperator(trial_fem_space.vector_space, trial_fem_space.get_refined_space(ncells).vector_space)
for ni,Pi in enumerate(Ps):P[ni,ni] = Pi
for ni,Pi in enumerate(Ps):
P[ni,ni] = Pi

mat = ComposedLinearOperator(trial_space, test_space, mat, P)

self._matrix[i,j] = mat
Expand Down
7 changes: 2 additions & 5 deletions psydac/api/postprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -953,12 +953,9 @@ def _reconstruct_spaces(self):
for subdomain_names, space_dict in subdomains_to_spaces.items():
if space_dict == {}:
continue
ncells_dict = {interior_name: interior_names_to_ncells[interior_name] for interior_name in subdomain_names}
# No need for a a dict until PR about non-conforming meshes is merged
# Check for conformity
ncells = list(ncells_dict.values())[0]
assert all(ncells_patch == ncells for ncells_patch in ncells_dict.values())

ncells = {interior_name: interior_names_to_ncells[interior_name] for interior_name in subdomain_names}

subdomain = domain.get_subdomain(subdomain_names)
space_name_0 = list(space_dict.keys())[0]
periodic = space_dict[space_name_0][2].get('periodic', None)
Expand Down
38 changes: 19 additions & 19 deletions psydac/feec/multipatch/examples/h1_source_pbms_conga_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
from psydac.feec.multipatch.operators import HodgeOperator
from psydac.feec.multipatch.plotting_utilities import plot_field
from psydac.feec.multipatch.multipatch_domain_utilities import build_multipatch_domain
from psydac.feec.multipatch.examples.ppc_test_cases import get_source_and_solution
from psydac.feec.multipatch.examples.ppc_test_cases import get_source_and_solution_OBSOLETE
from psydac.feec.multipatch.utilities import time_count
from psydac.feec.multipatch.non_matching_operators import construct_scalar_conforming_projection, construct_vector_conforming_projection

from psydac.linalg.utilities import array_to_psydac
from psydac.fem.basic import FemField
Expand Down Expand Up @@ -118,17 +119,15 @@ def solve_h1_source_pbm(
H0 = HodgeOperator(V0h, domain_h, backend_language=backend_language)
H1 = HodgeOperator(V1h, domain_h, backend_language=backend_language)

dH0_m = H0.get_dual_Hodge_sparse_matrix() # = mass matrix of V0
H0_m = H0.to_sparse_matrix() # = inverse mass matrix of V0
dH1_m = H1.get_dual_Hodge_sparse_matrix() # = mass matrix of V1
# H1_m = H1.to_sparse_matrix() # = inverse mass matrix of V1
H0_m = H0.to_sparse_matrix() # = mass matrix of V0
dH0_m = H0.get_dual_Hodge_sparse_matrix() # = inverse mass matrix of V0
H1_m = H1.to_sparse_matrix() # = mass matrix of V1
dH1_m = H1.get_dual_Hodge_sparse_matrix() # = inverse mass matrix of V1

print('conforming projection operators...')
# conforming Projections (should take into account the boundary conditions of the continuous deRham sequence)
cP0 = derham_h.conforming_projection(space='V0', hom_bc=True, backend_language=backend_language)
cP0_m = cP0.to_sparse_matrix()
# cP1 = derham_h.conforming_projection(space='V1', hom_bc=True, backend_language=backend_language)
# cP1_m = cP1.to_sparse_matrix()
cP0_m = construct_scalar_conforming_projection(V0h, hom_bc=[True,True])
# cP1_m = construct_vector_conforming_projection(V1h, domain_h, hom_bc=True)

if not os.path.exists(plot_dir):
os.makedirs(plot_dir)
Expand All @@ -138,7 +137,7 @@ def lift_u_bc(u_bc):
print('lifting the boundary condition in V0h... [warning: Not Tested Yet!]')
# note: for simplicity we apply the full P1 on u_bc, but we only need to set the boundary dofs
u_bc = lambdify(domain.coordinates, u_bc)
u_bc_log = [pull_2d_h1(u_bc, m) for m in mappings_list]
u_bc_log = [pull_2d_h1(u_bc, m.get_callable_mapping()) for m in mappings_list]
# it's a bit weird to apply P1 on the list of (pulled back) logical fields -- why not just apply it on u_bc ?
uh_bc = P0(u_bc_log)
ubc_c = uh_bc.coeffs.toarray()
Expand All @@ -150,20 +149,20 @@ def lift_u_bc(u_bc):

# Conga (projection-based) stiffness matrices:
# div grad:
pre_DG_m = - bD0_m.transpose() @ dH1_m @ bD0_m
pre_DG_m = - bD0_m.transpose() @ H1_m @ bD0_m

# jump penalization:
jump_penal_m = I0_m - cP0_m
JP0_m = jump_penal_m.transpose() * dH0_m * jump_penal_m
JP0_m = jump_penal_m.transpose() * H0_m * jump_penal_m

pre_A_m = cP0_m.transpose() @ ( eta * dH0_m - mu * pre_DG_m ) # useful for the boundary condition (if present)
pre_A_m = cP0_m.transpose() @ ( eta * H0_m - mu * pre_DG_m ) # useful for the boundary condition (if present)
A_m = pre_A_m @ cP0_m + gamma_h * JP0_m

print('getting the source and ref solution...')
# (not all the returned functions are useful here)
N_diag = 200
method = 'conga'
f_scal, f_vect, u_bc, ph_ref, uh_ref, p_ex, u_ex, phi, grad_phi = get_source_and_solution(
f_scal, f_vect, u_bc, p_ex, u_ex, phi, grad_phi = get_source_and_solution_OBSOLETE(
source_type=source_type, eta=eta, mu=mu, domain=domain, domain_name=domain_name,
refsol_params=[N_diag, method, source_proj],
)
Expand All @@ -173,26 +172,26 @@ def lift_u_bc(u_bc):
if source_proj == 'P_geom':
print('projecting the source with commuting projection P0...')
f = lambdify(domain.coordinates, f_scal)
f_log = [pull_2d_h1(f, m) for m in mappings_list]
f_log = [pull_2d_h1(f, m.get_callable_mapping()) for m in mappings_list]
f_h = P0(f_log)
f_c = f_h.coeffs.toarray()
b_c = dH0_m.dot(f_c)
b_c = H0_m.dot(f_c)

elif source_proj == 'P_L2':
print('projecting the source with L2 projection...')
v = element_of(V0h.symbolic_space, name='v')
expr = f_scal * v
l = LinearForm(v, integral(domain, expr))
lh = discretize(l, domain_h, V0h, backend=PSYDAC_BACKENDS[backend_language])
lh = discretize(l, domain_h, V0h)
b = lh.assemble()
b_c = b.toarray()
if plot_source:
f_c = H0_m.dot(b_c)
f_c = dH0_m.dot(b_c)
else:
raise ValueError(source_proj)

if plot_source:
plot_field(numpy_coeffs=f_c, Vh=V0h, space_kind='h1', domain=domain, title='f_h with P = '+source_proj, filename=plot_dir+'/fh_'+source_proj+'.png', hide_plot=hide_plots)
plot_field(numpy_coeffs=f_c, Vh=V0h, space_kind='h1', domain=domain, title='f_h with P = '+source_proj, filename=plot_dir+'fh_'+source_proj+'.png', hide_plot=hide_plots)

ubc_c = lift_u_bc(u_bc)

Expand Down Expand Up @@ -265,6 +264,7 @@ def lift_u_bc(u_bc):
mu=1, #1,
domain_name=domain_name,
source_type=source_type,
source_proj = 'P_geom',
backend_language='pyccel-gcc',
plot_source=True,
plot_dir='./plots/h1_tests_source_february/'+run_dir,
Expand Down
89 changes: 62 additions & 27 deletions psydac/feec/multipatch/examples/hcurl_eigen_pbms_conga_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
from psydac.feec.multipatch.multipatch_domain_utilities import build_multipatch_domain
from psydac.feec.multipatch.plotting_utilities import plot_field
from psydac.feec.multipatch.utilities import time_count
from psydac.feec.multipatch.non_matching_operators import construct_scalar_conforming_projection, construct_vector_conforming_projection

def hcurl_solve_eigen_pbm(nc=4, deg=4, domain_name='pretzel_f', backend_language='python', mu=1, nu=1, gamma_h=10,
def hcurl_solve_eigen_pbm(nc=4, deg=4, domain_name='pretzel_f', backend_language='python', mu=1, nu=0, gamma_h=10,
FrederikSchnack marked this conversation as resolved.
Show resolved Hide resolved
sigma=None, nb_eigs=4, nb_eigs_plot=4,
plot_dir=None, hide_plots=True, m_load_dir="",):
plot_dir=None, hide_plots=True, m_load_dir="",skip_eigs_threshold = 1e-7,):
"""
solver for the eigenvalue problem: find lambda in R and u in H0(curl), such that

Expand Down Expand Up @@ -71,7 +72,7 @@ def hcurl_solve_eigen_pbm(nc=4, deg=4, domain_name='pretzel_f', backend_language

print('building symbolic and discrete derham sequences...')
derham = Derham(domain, ["H1", "Hcurl", "L2"])
derham_h = discretize(derham, domain_h, degree=degree, backend=PSYDAC_BACKENDS[backend_language])
derham_h = discretize(derham, domain_h, degree=degree)

V0h = derham_h.V0
V1h = derham_h.V1
Expand All @@ -94,18 +95,17 @@ def hcurl_solve_eigen_pbm(nc=4, deg=4, domain_name='pretzel_f', backend_language
H1 = HodgeOperator(V1h, domain_h, backend_language=backend_language, load_dir=m_load_dir, load_space_index=1)
H2 = HodgeOperator(V2h, domain_h, backend_language=backend_language, load_dir=m_load_dir, load_space_index=2)

dH0_m = H0.get_dual_Hodge_sparse_matrix() # = mass matrix of V0
H0_m = H0.to_sparse_matrix() # = inverse mass matrix of V0
dH1_m = H1.get_dual_Hodge_sparse_matrix() # = mass matrix of V1
H1_m = H1.to_sparse_matrix() # = inverse mass matrix of V1
dH2_m = H2.get_dual_Hodge_sparse_matrix() # = mass matrix of V2
H0_m = H0.to_sparse_matrix() # = mass matrix of V0
dH0_m = H0.get_dual_Hodge_sparse_matrix() # = inverse mass matrix of V0
H1_m = H1.to_sparse_matrix() # = mass matrix of V1
dH1_m = H1.get_dual_Hodge_sparse_matrix() # = inverse mass matrix of V1
H2_m = H2.to_sparse_matrix() # = mass matrix of V2
# dH2_m = H2.get_dual_Hodge_sparse_matrix() # = inverse mass matrix of V2

print('conforming projection operators...')
# conforming Projections (should take into account the boundary conditions of the continuous deRham sequence)
cP0 = derham_h.conforming_projection(space='V0', hom_bc=True, backend_language=backend_language, load_dir=m_load_dir)
cP1 = derham_h.conforming_projection(space='V1', hom_bc=True, backend_language=backend_language, load_dir=m_load_dir)
cP0_m = cP0.to_sparse_matrix()
cP1_m = cP1.to_sparse_matrix()
cP0_m = construct_scalar_conforming_projection(V0h, hom_bc=[True, True])
cP1_m = construct_vector_conforming_projection(V1h, hom_bc=[True, True])

print('broken differential operators...')
bD0, bD1 = derham_h.broken_derivatives_as_operators
Expand All @@ -118,33 +118,59 @@ def hcurl_solve_eigen_pbm(nc=4, deg=4, domain_name='pretzel_f', backend_language
# Conga (projection-based) stiffness matrices
# curl curl:
print('curl-curl stiffness matrix...')
pre_CC_m = bD1_m.transpose() @ dH2_m @ bD1_m
pre_CC_m = bD1_m.transpose() @ H2_m @ bD1_m
CC_m = cP1_m.transpose() @ pre_CC_m @ cP1_m # Conga stiffness matrix

# grad div:
print('grad-div stiffness matrix...')
pre_GD_m = - dH1_m @ bD0_m @ cP0_m @ H0_m @ cP0_m.transpose() @ bD0_m.transpose() @ dH1_m
pre_GD_m = - H1_m @ bD0_m @ cP0_m @ dH0_m @ cP0_m.transpose() @ bD0_m.transpose() @ H1_m
GD_m = cP1_m.transpose() @ pre_GD_m @ cP1_m # Conga stiffness matrix

# jump penalization in V1h:
jump_penal_m = I1_m - cP1_m
JP_m = jump_penal_m.transpose() * dH1_m * jump_penal_m
JP_m = jump_penal_m.transpose() * H1_m * jump_penal_m

print('computing the full operator matrix...')
print('mu = {}'.format(mu))
print('nu = {}'.format(nu))
A_m = mu * CC_m - nu * GD_m + gamma_h * JP_m

eigenvalues, eigenvectors = get_eigenvalues(nb_eigs, sigma, A_m, dH1_m)
if False: #gneralized problen
print('adding jump stabilization to RHS of generalized eigenproblem...')
B_m = cP1_m.transpose() @ H1_m @ cP1_m + JS_m
else:
B_m = H1_m

print('solving matrix eigenproblem...')
all_eigenvalues, all_eigenvectors_transp = get_eigenvalues(nb_eigs, sigma, A_m, B_m)
#Eigenvalue processing

zero_eigenvalues = []
if skip_eigs_threshold is not None:
eigenvalues = []
eigenvectors = []
for val, vect in zip(all_eigenvalues, all_eigenvectors_transp.T):
if abs(val) < skip_eigs_threshold:
zero_eigenvalues.append(val)
# we skip the eigenvector
else:
eigenvalues.append(val)
eigenvectors.append(vect)
else:
eigenvalues = all_eigenvalues
eigenvectors = all_eigenvectors_transp.T



# plot first eigenvalues

for i in range(min(nb_eigs_plot, nb_eigs)):
for i in range(min(nb_eigs_plot, len(eigenvalues))):

print('looking at emode i = {}... '.format(i))
lambda_i = eigenvalues[i]
emode_i = np.real(eigenvectors[:,i])
norm_emode_i = np.dot(emode_i,dH1_m.dot(emode_i))
print('looking at emode i = {}: {}... '.format(i, lambda_i))

emode_i = np.real(eigenvectors[i])
norm_emode_i = np.dot(emode_i,H1_m.dot(emode_i))
print('norm of computed eigenmode: ', norm_emode_i)
eh_c = emode_i/norm_emode_i # numpy coeffs of the normalized eigenmode
plot_field(numpy_coeffs=eh_c, Vh=V1h, space_kind='hcurl', domain=domain, title='mode e_{}, lambda_{}={}'.format(i,i,lambda_i),
Expand Down Expand Up @@ -203,8 +229,8 @@ def get_eigenvalues(nb_eigs, sigma, A_m, M_m):

t_stamp_full = time_count()

quick_run = True
# quick_run = False
# quick_run = True
quick_run = False

if quick_run:
domain_name = 'curved_L_shape'
Expand All @@ -214,23 +240,32 @@ def get_eigenvalues(nb_eigs, sigma, A_m, M_m):
nc = 8
deg = 4

domain_name = 'pretzel_f'
# domain_name = 'curved_L_shape'
#domain_name = 'pretzel_f'
domain_name = 'curved_L_shape'
nc = 10
deg = 2
deg = 3

sigma = 7
nb_eigs_solve = 7
nb_eigs_plot = 7
skip_eigs_threshold = 1e-7

m_load_dir = 'matrices_{}_nc={}_deg={}/'.format(domain_name, nc, deg)
run_dir = 'eigenpbm_{}_nc={}_deg={}/'.format(domain_name, nc, deg)
hcurl_solve_eigen_pbm(
nc=nc, deg=deg,
nu=0,
mu=1, #1,
sigma=1,
domain_name=domain_name,
backend_language='pyccel-gcc',
plot_dir='./plots/tests_source_february/'+run_dir,
hide_plots=True,
m_load_dir=m_load_dir,
m_load_dir=m_load_dir,
gamma_h=0,
sigma=sigma,
nb_eigs=nb_eigs_solve,
nb_eigs_plot=nb_eigs_plot,
skip_eigs_threshold=skip_eigs_threshold,
)

time_count(t_stamp_full, msg='full program')
Loading
Loading