From 292ec8c3e2efa4914c73c74b787abf71d1b83cdf Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 12:05:03 -0400 Subject: [PATCH 01/16] added classes --- festim/__init__.py | 2 ++ festim/species.py | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 festim/species.py diff --git a/festim/__init__.py b/festim/__init__.py index c5bde34d8..1500688ac 100644 --- a/festim/__init__.py +++ b/festim/__init__.py @@ -21,4 +21,6 @@ from .mesh.mesh import Mesh from .mesh.mesh_1d import Mesh1D +from .species import Species, Trap + from .hydrogen_transport_problem import HydrogenTransportProblem diff --git a/festim/species.py b/festim/species.py new file mode 100644 index 000000000..78587f02a --- /dev/null +++ b/festim/species.py @@ -0,0 +1,13 @@ +class Species: + def __init__(self, name=None) -> None: + self.name = name + + self.solution = None + self.prev_solution = None + self.test_function = None + self.form = None + + +class Trap(Species): + def __init__(self, name=None) -> None: + super().__init__(name) \ No newline at end of file From 7d0dfc4976d9a3e01dfc8be4e4c106f785882b29 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 12:08:22 -0400 Subject: [PATCH 02/16] added some docstrings --- festim/species.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/festim/species.py b/festim/species.py index 78587f02a..8b6b20df3 100644 --- a/festim/species.py +++ b/festim/species.py @@ -1,13 +1,29 @@ class Species: - def __init__(self, name=None) -> None: + """ + Hydrogen Transport Problem. + + Args: + name (str, optional): a name given to the species. Defaults to None. + + Attributes: + name (str): a name given to the species. + solution (dolfinx.Function or ...): the solution for the current timestep + prev_solution (dolfinx.Function or ...): the solution for the previous timestep + test_function (ufl.TestFunction or ...): the testfunction associated with this species + """ + def __init__(self, name:str=None) -> None: + """_summary_ + + Args: + name (str, optional): a name given to the species. Defaults to None. + """ self.name = name self.solution = None self.prev_solution = None self.test_function = None - self.form = None class Trap(Species): - def __init__(self, name=None) -> None: + def __init__(self, name:str=None) -> None: super().__init__(name) \ No newline at end of file From 30903ead50ab4dedd72134c4392ee41237768d78 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 12:30:23 -0400 Subject: [PATCH 03/16] removed sympy from init --- festim/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/festim/__init__.py b/festim/__init__.py index 1500688ac..ca22327fe 100644 --- a/festim/__init__.py +++ b/festim/__init__.py @@ -13,8 +13,6 @@ __version__ = "unknown" -import sympy as sp - R = 8.314462618 # Gas constant J.mol-1.K-1 k_B = 8.6173303e-5 # Boltzmann constant eV.K-1 From 86b7a0f37318387c898cd4edda523bbe0274e879 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 12:35:17 -0400 Subject: [PATCH 04/16] added the permeation problem as a test --- test/test_permeation_problem.py | 128 ++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 test/test_permeation_problem.py diff --git a/test/test_permeation_problem.py b/test/test_permeation_problem.py new file mode 100644 index 000000000..57b2b9b93 --- /dev/null +++ b/test/test_permeation_problem.py @@ -0,0 +1,128 @@ +from mpi4py import MPI +from petsc4py import PETSc +from dolfinx.io import XDMFFile +from dolfinx.fem import ( + Constant, + dirichletbc, + Function, + locate_dofs_topological, + form, + assemble_scalar, +) +from dolfinx.fem.petsc import ( + NonlinearProblem, +) +from dolfinx.nls.petsc import NewtonSolver +from ufl import ( + dot, + grad, + TestFunction, + exp, + FacetNormal, + dx, + ds, +) +from dolfinx import log +import numpy as np +import tqdm.autonotebook + + +import festim as F + +# mesh nodes +vertices = np.linspace(0, 3e-4, num=1001) + +my_mesh = F.Mesh1D(vertices) + +my_model = F.HydrogenTransportProblem() +my_model.mesh = my_mesh + +my_model.initialise() + +V = my_model.function_space +u = Function(V) +u_n = Function(V) +v = TestFunction(V) + + +temperature = 500 +k_B = F.k_B + +# TODO this should be a property of Mesh +n = FacetNormal(my_mesh.mesh) + + +def siverts_law(T, S_0, E_S, pressure): + S = S_0 * exp(-E_S / k_B / T) + return S * pressure**0.5 + +fdim = my_mesh.mesh.topology.dim - 1 +left_facets = my_model.facet_tags.find(1) +left_dofs = locate_dofs_topological(V, fdim, left_facets) +right_facets = my_model.facet_tags.find(2) +right_dofs = locate_dofs_topological(V, fdim, right_facets) + +surface_conc = siverts_law(T=temperature, S_0=4.02e21, E_S=1.04, pressure=100) +bc_sieverts = dirichletbc( + Constant(my_mesh.mesh, PETSc.ScalarType(surface_conc)), left_dofs, V +) +bc_outgas = dirichletbc(Constant(my_mesh.mesh, PETSc.ScalarType(0)), right_dofs, V) +bcs = [bc_sieverts, bc_outgas] + +D_0 = 1.9e-7 +E_D = 0.2 + +D = D_0 * exp(-E_D / k_B / temperature) + +dt = 1 / 20 +final_time = 50 +num_steps = int(final_time / dt) + +f = Constant(my_mesh.mesh, (PETSc.ScalarType(0))) +F = dot(D * grad(u), grad(v)) * dx +F += ((u - u_n) / dt) * v * dx + +problem = NonlinearProblem(F, u, bcs=bcs) +solver = NewtonSolver(MPI.COMM_WORLD, problem) +solver.convergence_criterion = "incremental" +solver.rtol = 1e-10 +solver.atol = 1e10 +solver.report = True +ksp = solver.krylov_solver +opts = PETSc.Options() +option_prefix = ksp.getOptionsPrefix() +opts[f"{option_prefix}ksp_type"] = "cg" +opts[f"{option_prefix}pc_type"] = "gamg" +opts[f"{option_prefix}pc_factor_mat_solver_type"] = "mumps" +ksp.setFromOptions() +# log.set_log_level(log.LogLevel.INFO) + +mobile_xdmf = XDMFFile(MPI.COMM_WORLD, "mobile_concentration.xdmf", "w") +mobile_xdmf.write_mesh(my_mesh.mesh) + +flux_values = [] +times = [] +t = 0 +progress = tqdm.autonotebook.tqdm(desc="Solving H transport problem", total=num_steps) +for i in range(num_steps): + progress.update(1) + t += dt + + solver.solve(u) + + # post process + surface_flux = form(D * dot(grad(u), n) * ds(2)) + flux = assemble_scalar(surface_flux) + flux_values.append(flux) + times.append(t) + + # export + np.savetxt("outgassing_flux.txt", np.array(flux_values)) + np.savetxt("times.txt", np.array(times)) + + mobile_xdmf.write_function(u, t) + + # update previous solution + u_n.x.array[:] = u.x.array[:] + +mobile_xdmf.close() \ No newline at end of file From 9d0b641ebc0a97cc143f24d19b2db4e6429671bd Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 13:12:30 -0400 Subject: [PATCH 05/16] added test --- test/test_permeation_problem.py | 179 +++++++++++++++++--------------- 1 file changed, 93 insertions(+), 86 deletions(-) diff --git a/test/test_permeation_problem.py b/test/test_permeation_problem.py index 57b2b9b93..491c4370c 100644 --- a/test/test_permeation_problem.py +++ b/test/test_permeation_problem.py @@ -29,100 +29,107 @@ import festim as F -# mesh nodes -vertices = np.linspace(0, 3e-4, num=1001) +def test_permeation_problem(): + # mesh nodes + vertices = np.linspace(0, 3e-4, num=1001) -my_mesh = F.Mesh1D(vertices) + my_mesh = F.Mesh1D(vertices) -my_model = F.HydrogenTransportProblem() -my_model.mesh = my_mesh + my_model = F.HydrogenTransportProblem() + my_model.mesh = my_mesh -my_model.initialise() + my_model.initialise() -V = my_model.function_space -u = Function(V) -u_n = Function(V) -v = TestFunction(V) + V = my_model.function_space + u = Function(V) + u_n = Function(V) + v = TestFunction(V) -temperature = 500 -k_B = F.k_B + temperature = 500 + k_B = F.k_B -# TODO this should be a property of Mesh -n = FacetNormal(my_mesh.mesh) + # TODO this should be a property of Mesh + n = FacetNormal(my_mesh.mesh) -def siverts_law(T, S_0, E_S, pressure): - S = S_0 * exp(-E_S / k_B / T) - return S * pressure**0.5 + def siverts_law(T, S_0, E_S, pressure): + S = S_0 * exp(-E_S / k_B / T) + return S * pressure**0.5 -fdim = my_mesh.mesh.topology.dim - 1 -left_facets = my_model.facet_tags.find(1) -left_dofs = locate_dofs_topological(V, fdim, left_facets) -right_facets = my_model.facet_tags.find(2) -right_dofs = locate_dofs_topological(V, fdim, right_facets) + fdim = my_mesh.mesh.topology.dim - 1 + left_facets = my_model.facet_tags.find(1) + left_dofs = locate_dofs_topological(V, fdim, left_facets) + right_facets = my_model.facet_tags.find(2) + right_dofs = locate_dofs_topological(V, fdim, right_facets) -surface_conc = siverts_law(T=temperature, S_0=4.02e21, E_S=1.04, pressure=100) -bc_sieverts = dirichletbc( - Constant(my_mesh.mesh, PETSc.ScalarType(surface_conc)), left_dofs, V -) -bc_outgas = dirichletbc(Constant(my_mesh.mesh, PETSc.ScalarType(0)), right_dofs, V) -bcs = [bc_sieverts, bc_outgas] - -D_0 = 1.9e-7 -E_D = 0.2 - -D = D_0 * exp(-E_D / k_B / temperature) - -dt = 1 / 20 -final_time = 50 -num_steps = int(final_time / dt) - -f = Constant(my_mesh.mesh, (PETSc.ScalarType(0))) -F = dot(D * grad(u), grad(v)) * dx -F += ((u - u_n) / dt) * v * dx - -problem = NonlinearProblem(F, u, bcs=bcs) -solver = NewtonSolver(MPI.COMM_WORLD, problem) -solver.convergence_criterion = "incremental" -solver.rtol = 1e-10 -solver.atol = 1e10 -solver.report = True -ksp = solver.krylov_solver -opts = PETSc.Options() -option_prefix = ksp.getOptionsPrefix() -opts[f"{option_prefix}ksp_type"] = "cg" -opts[f"{option_prefix}pc_type"] = "gamg" -opts[f"{option_prefix}pc_factor_mat_solver_type"] = "mumps" -ksp.setFromOptions() -# log.set_log_level(log.LogLevel.INFO) - -mobile_xdmf = XDMFFile(MPI.COMM_WORLD, "mobile_concentration.xdmf", "w") -mobile_xdmf.write_mesh(my_mesh.mesh) - -flux_values = [] -times = [] -t = 0 -progress = tqdm.autonotebook.tqdm(desc="Solving H transport problem", total=num_steps) -for i in range(num_steps): - progress.update(1) - t += dt - - solver.solve(u) - - # post process - surface_flux = form(D * dot(grad(u), n) * ds(2)) - flux = assemble_scalar(surface_flux) - flux_values.append(flux) - times.append(t) - - # export - np.savetxt("outgassing_flux.txt", np.array(flux_values)) - np.savetxt("times.txt", np.array(times)) - - mobile_xdmf.write_function(u, t) - - # update previous solution - u_n.x.array[:] = u.x.array[:] - -mobile_xdmf.close() \ No newline at end of file + surface_conc = siverts_law(T=temperature, S_0=4.02e21, E_S=1.04, pressure=100) + bc_sieverts = dirichletbc( + Constant(my_mesh.mesh, PETSc.ScalarType(surface_conc)), left_dofs, V + ) + bc_outgas = dirichletbc(Constant(my_mesh.mesh, PETSc.ScalarType(0)), right_dofs, V) + bcs = [bc_sieverts, bc_outgas] + + D_0 = 1.9e-7 + E_D = 0.2 + + D = D_0 * exp(-E_D / k_B / temperature) + + dt = 1 / 20 + final_time = 50 + + # f = Constant(my_mesh.mesh, (PETSc.ScalarType(0))) + variational_form = dot(D * grad(u), grad(v)) * dx + variational_form += ((u - u_n) / dt) * v * dx + + problem = NonlinearProblem(variational_form, u, bcs=bcs) + solver = NewtonSolver(MPI.COMM_WORLD, problem) + + my_model.settings.solver.convergence_criterion = "incremental" + # solver.convergence_criterion = "incremental" + solver.rtol = 1e-10 + solver.atol = 1e10 + + + solver.report = True + ksp = solver.krylov_solver + opts = PETSc.Options() + option_prefix = ksp.getOptionsPrefix() + opts[f"{option_prefix}ksp_type"] = "cg" + opts[f"{option_prefix}pc_type"] = "gamg" + opts[f"{option_prefix}pc_factor_mat_solver_type"] = "mumps" + ksp.setFromOptions() + # log.set_log_level(log.LogLevel.INFO) + + mobile_xdmf = XDMFFile(MPI.COMM_WORLD, "mobile_concentration.xdmf", "w") + mobile_xdmf.write_mesh(my_mesh.mesh) + + flux_values = [] + times = [] + t = 0 + progress = tqdm.autonotebook.tqdm(desc="Solving H transport problem", total=final_time) + while t < final_time: + progress.update(dt) + t += dt + + solver.solve(u) + + # post process + surface_flux = form(D * dot(grad(u), n) * ds(2)) + flux = assemble_scalar(surface_flux) + flux_values.append(flux) + times.append(t) + + # export + np.savetxt("outgassing_flux.txt", np.array(flux_values)) + np.savetxt("times.txt", np.array(times)) + + mobile_xdmf.write_function(u, t) + + # update previous solution + u_n.x.array[:] = u.x.array[:] + + mobile_xdmf.close() + +if __name__=="__main__": + test_permeation_problem() \ No newline at end of file From 399f907b0c51b9fa603e59e51e6febab2f61a0bd Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 13:24:51 -0400 Subject: [PATCH 06/16] Integrate Species with HydrogenTransportProblem --- festim/hydrogen_transport_problem.py | 13 ++++++++++++- test/test_permeation_problem.py | 12 +++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/festim/hydrogen_transport_problem.py b/festim/hydrogen_transport_problem.py index d3057028f..7ade147bd 100644 --- a/festim/hydrogen_transport_problem.py +++ b/festim/hydrogen_transport_problem.py @@ -1,7 +1,9 @@ -import numpy as np from dolfinx import fem import ufl +from dolfinx.fem import Function +from ufl import TestFunction + class HydrogenTransportProblem: """ @@ -52,7 +54,16 @@ def initialise(self): self.dx, self.ds, ) = self.mesh.create_measures_and_tags(self.function_space) + self.create_functions_for_species() def define_function_space(self): elements = ufl.FiniteElement("CG", self.mesh.mesh.ufl_cell(), 1) self.function_space = fem.FunctionSpace(self.mesh.mesh, elements) + + def create_functions_for_species(self): + """Creates for each species the solution, prev solution and test function + """ + for spe in self.species: + spe.solution = Function(self.function_space) + spe.prev_solution = Function(self.function_space) + spe.test_function = TestFunction(self.function_space) diff --git a/test/test_permeation_problem.py b/test/test_permeation_problem.py index 491c4370c..c12a7bf45 100644 --- a/test/test_permeation_problem.py +++ b/test/test_permeation_problem.py @@ -38,12 +38,15 @@ def test_permeation_problem(): my_model = F.HydrogenTransportProblem() my_model.mesh = my_mesh + mobile_H = F.Species("H") + my_model.species = [mobile_H] + my_model.initialise() V = my_model.function_space - u = Function(V) - u_n = Function(V) - v = TestFunction(V) + u = mobile_H.solution + u_n = mobile_H.prev_solution + v = mobile_H.test_function temperature = 500 @@ -85,8 +88,7 @@ def siverts_law(T, S_0, E_S, pressure): problem = NonlinearProblem(variational_form, u, bcs=bcs) solver = NewtonSolver(MPI.COMM_WORLD, problem) - my_model.settings.solver.convergence_criterion = "incremental" - # solver.convergence_criterion = "incremental" + solver.convergence_criterion = "incremental" solver.rtol = 1e-10 solver.atol = 1e10 From 83954ddcfd8cac2b5b7c11bed35953f47f46ff84 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 13:32:03 -0400 Subject: [PATCH 07/16] using Constant objects --- test/test_permeation_problem.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test_permeation_problem.py b/test/test_permeation_problem.py index c12a7bf45..a6dd1580e 100644 --- a/test/test_permeation_problem.py +++ b/test/test_permeation_problem.py @@ -49,7 +49,7 @@ def test_permeation_problem(): v = mobile_H.test_function - temperature = 500 + temperature = Constant(my_mesh.mesh, 500.) k_B = F.k_B # TODO this should be a property of Mesh @@ -73,12 +73,12 @@ def siverts_law(T, S_0, E_S, pressure): bc_outgas = dirichletbc(Constant(my_mesh.mesh, PETSc.ScalarType(0)), right_dofs, V) bcs = [bc_sieverts, bc_outgas] - D_0 = 1.9e-7 - E_D = 0.2 + D_0 = Constant(my_mesh.mesh, 1.9e-7) + E_D = Constant(my_mesh.mesh, 0.2) D = D_0 * exp(-E_D / k_B / temperature) - dt = 1 / 20 + dt = Constant(my_mesh.mesh, 1 / 20) final_time = 50 # f = Constant(my_mesh.mesh, (PETSc.ScalarType(0))) @@ -111,8 +111,8 @@ def siverts_law(T, S_0, E_S, pressure): t = 0 progress = tqdm.autonotebook.tqdm(desc="Solving H transport problem", total=final_time) while t < final_time: - progress.update(dt) - t += dt + progress.update(float(dt)) + t += float(dt) solver.solve(u) From 871fe75f84b7648e7d56ac919cc03a997cd7726c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 13:33:21 -0400 Subject: [PATCH 08/16] better name for method --- festim/hydrogen_transport_problem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/festim/hydrogen_transport_problem.py b/festim/hydrogen_transport_problem.py index 7ade147bd..fd7dc6060 100644 --- a/festim/hydrogen_transport_problem.py +++ b/festim/hydrogen_transport_problem.py @@ -60,7 +60,7 @@ def define_function_space(self): elements = ufl.FiniteElement("CG", self.mesh.mesh.ufl_cell(), 1) self.function_space = fem.FunctionSpace(self.mesh.mesh, elements) - def create_functions_for_species(self): + def assign_functions_to_species(self): """Creates for each species the solution, prev solution and test function """ for spe in self.species: From f987d9571e0db2e0e9a336aadb2e3f7a26a6cd98 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 13:33:37 -0400 Subject: [PATCH 09/16] fix --- festim/hydrogen_transport_problem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/festim/hydrogen_transport_problem.py b/festim/hydrogen_transport_problem.py index fd7dc6060..c5e168a48 100644 --- a/festim/hydrogen_transport_problem.py +++ b/festim/hydrogen_transport_problem.py @@ -54,7 +54,7 @@ def initialise(self): self.dx, self.ds, ) = self.mesh.create_measures_and_tags(self.function_space) - self.create_functions_for_species() + self.assign_functions_to_species() def define_function_space(self): elements = ufl.FiniteElement("CG", self.mesh.mesh.ufl_cell(), 1) From 72d7341547e6893d0c49ca1903ecea2dc25510af Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 13:52:15 -0400 Subject: [PATCH 10/16] added usage to docstrings --- festim/species.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/festim/species.py b/festim/species.py index 8b6b20df3..1e3ea91a1 100644 --- a/festim/species.py +++ b/festim/species.py @@ -1,6 +1,6 @@ class Species: """ - Hydrogen Transport Problem. + Hydrogen species class for H transport simulation. Args: name (str, optional): a name given to the species. Defaults to None. @@ -10,6 +10,15 @@ class Species: solution (dolfinx.Function or ...): the solution for the current timestep prev_solution (dolfinx.Function or ...): the solution for the previous timestep test_function (ufl.TestFunction or ...): the testfunction associated with this species + + Usage: + >>> from festim import Species, HTransportProblem + >>> species = Species(name="H") + >>> species.name + 'H' + >>> my_model = HTransportProblem() + >>> my_model.species.append(species) + """ def __init__(self, name:str=None) -> None: """_summary_ @@ -25,5 +34,23 @@ def __init__(self, name:str=None) -> None: class Trap(Species): + """Trap species class for H transport simulation. + + Args: + name (str, optional): a name given to the trap. Defaults to None. + + Attributes: + name (str): a name given to the trap. + attributes of Species class + + Usage: + >>> from festim import Trap, HTransportProblem + >>> trap = Trap(name="Trap") + >>> trap.name + 'Trap' + >>> my_model = HTransportProblem() + >>> my_model.species.append(trap) + + """ def __init__(self, name:str=None) -> None: super().__init__(name) \ No newline at end of file From 2dd91eb9221f2da21b9f8cd5df84044c788a59eb Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 14:06:27 -0400 Subject: [PATCH 11/16] updated type --- festim/species.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/festim/species.py b/festim/species.py index 1e3ea91a1..f2fea1ca3 100644 --- a/festim/species.py +++ b/festim/species.py @@ -7,9 +7,9 @@ class Species: Attributes: name (str): a name given to the species. - solution (dolfinx.Function or ...): the solution for the current timestep - prev_solution (dolfinx.Function or ...): the solution for the previous timestep - test_function (ufl.TestFunction or ...): the testfunction associated with this species + solution (dolfinx.fem.Function or ...): the solution for the current timestep + prev_solution (dolfinx.fem.Function or ...): the solution for the previous timestep + test_function (ufl.Argument or ...): the testfunction associated with this species Usage: >>> from festim import Species, HTransportProblem From 312cdf9e6b76001ebc6bad41fdbc50f530d6f60b Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 14:06:54 -0400 Subject: [PATCH 12/16] added usage and attributes to hydrogenTransportProblem --- festim/hydrogen_transport_problem.py | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/festim/hydrogen_transport_problem.py b/festim/hydrogen_transport_problem.py index c5e168a48..7a1533e83 100644 --- a/festim/hydrogen_transport_problem.py +++ b/festim/hydrogen_transport_problem.py @@ -12,10 +12,40 @@ class HydrogenTransportProblem: Args: mesh (festim.Mesh): the mesh of the model subdomains (list of festim.Subdomain): the subdomains of the model + species (list of festim.Species): the species of the model Attributes: mesh (festim.Mesh): the mesh of the model + subdomains (list of festim.Subdomain): the subdomains of the model + species (list of festim.Species): the species of the model + temperature (dolfinx.Function): the temperature of the model + boundary_conditions (list of festim.BoundaryCondition): the boundary conditions of the model + solver_parameters (dict): the solver parameters of the model + exports (list of festim.Export): the exports of the model + dx (dolfinx.fem.dx): the volume measure of the model + ds (dolfinx.fem.ds): the surface measure of the model + function_space (dolfinx.fem.FunctionSpace): the function space of the model + facet_tags (dolfinx.cpp.mesh.MeshTags): the facet tags of the model + volume_tags (dolfinx.cpp.mesh.MeshTags): the volume tags of the model + + + Usage: + >>> import festim as F + >>> my_model = F.HydrogenTransportProblem() + >>> my_model.mesh = F.Mesh(...) + >>> my_model.subdomains = [F.Subdomain(...)] + >>> my_model.species = [F.Species(name="H"), F.Species(name="Trap")] + >>> my_model.initialise() + + or + >>> my_model = F.HydrogenTransportProblem( + ... mesh=F.Mesh(...), + ... subdomains=[F.Subdomain(...)], + ... species=[F.Species(name="H"), F.Species(name="Trap")], + ... ) + >>> my_model.initialise() + """ def __init__( From 3566ea108e1c9fb3a4c553adef18cd0073326d53 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 6 Oct 2023 14:08:37 -0400 Subject: [PATCH 13/16] added test --- test/test_permeation_problem.py | 2 -- test/test_species.py | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 test/test_species.py diff --git a/test/test_permeation_problem.py b/test/test_permeation_problem.py index a6dd1580e..696cdfb86 100644 --- a/test/test_permeation_problem.py +++ b/test/test_permeation_problem.py @@ -4,7 +4,6 @@ from dolfinx.fem import ( Constant, dirichletbc, - Function, locate_dofs_topological, form, assemble_scalar, @@ -16,7 +15,6 @@ from ufl import ( dot, grad, - TestFunction, exp, FacetNormal, dx, diff --git a/test/test_species.py b/test/test_species.py new file mode 100644 index 000000000..e81b43e9f --- /dev/null +++ b/test/test_species.py @@ -0,0 +1,27 @@ +import festim as F +import dolfinx +import ufl +import numpy as np + + +def test_assign_functions_to_species(): + """Test that checks if the function assign_functions_to_species + creates the correct attributes for each species + """ + + + mesh = F.Mesh1D(vertices=np.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])) + model = F.HydrogenTransportProblem( + mesh=mesh, + species=[F.Species(name="H"), F.Species(name="Trap")], + ) + model.define_function_space() + model.assign_functions_to_species() + + for spe in model.species: + assert spe.solution is not None + assert spe.prev_solution is not None + assert spe.test_function is not None + assert isinstance(spe.solution, dolfinx.fem.Function) + assert isinstance(spe.prev_solution, dolfinx.fem.Function) + assert isinstance(spe.test_function, ufl.Argument) \ No newline at end of file From d67b558cb28e14e03eaf6bc499bd80ed8c8ace0b Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Sun, 8 Oct 2023 18:17:26 -0400 Subject: [PATCH 14/16] pip install requirements + added tqdm in requirements --- .github/workflows/ci.yml | 4 ++-- setup.cfg | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d003c6518..b2f560000 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,10 +21,10 @@ jobs: run: | mamba install -c conda-forge fenics-dolfinx - - name: Install dependencies + - name: Install local package and dependencies shell: bash -l {0} run: | - pip install pytest pytest-cov + pip install .[test] - name: Run tests shell: bash -l {0} diff --git a/setup.cfg b/setup.cfg index 57de6f86a..5d988731b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,10 @@ project_urls = [options] packages = find: python_requires= >=3.6 +install_requires = + tqdm [options.extras_require] -tests = +test = pytest >= 5.4.3 + pytest-cov From 81efe48a8b99a6e714da0fe286e9d6c28066cfde Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Sun, 8 Oct 2023 18:18:16 -0400 Subject: [PATCH 15/16] black formatted --- festim/hydrogen_transport_problem.py | 5 ++--- festim/species.py | 14 ++++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/festim/hydrogen_transport_problem.py b/festim/hydrogen_transport_problem.py index 7a1533e83..4e6d14a55 100644 --- a/festim/hydrogen_transport_problem.py +++ b/festim/hydrogen_transport_problem.py @@ -45,7 +45,7 @@ class HydrogenTransportProblem: ... species=[F.Species(name="H"), F.Species(name="Trap")], ... ) >>> my_model.initialise() - + """ def __init__( @@ -91,8 +91,7 @@ def define_function_space(self): self.function_space = fem.FunctionSpace(self.mesh.mesh, elements) def assign_functions_to_species(self): - """Creates for each species the solution, prev solution and test function - """ + """Creates for each species the solution, prev solution and test function""" for spe in self.species: spe.solution = Function(self.function_space) spe.prev_solution = Function(self.function_space) diff --git a/festim/species.py b/festim/species.py index f2fea1ca3..18ed7683d 100644 --- a/festim/species.py +++ b/festim/species.py @@ -10,7 +10,7 @@ class Species: solution (dolfinx.fem.Function or ...): the solution for the current timestep prev_solution (dolfinx.fem.Function or ...): the solution for the previous timestep test_function (ufl.Argument or ...): the testfunction associated with this species - + Usage: >>> from festim import Species, HTransportProblem >>> species = Species(name="H") @@ -20,7 +20,8 @@ class Species: >>> my_model.species.append(species) """ - def __init__(self, name:str=None) -> None: + + def __init__(self, name: str = None) -> None: """_summary_ Args: @@ -32,13 +33,13 @@ def __init__(self, name:str=None) -> None: self.prev_solution = None self.test_function = None - + class Trap(Species): """Trap species class for H transport simulation. Args: name (str, optional): a name given to the trap. Defaults to None. - + Attributes: name (str): a name given to the trap. attributes of Species class @@ -52,5 +53,6 @@ class Trap(Species): >>> my_model.species.append(trap) """ - def __init__(self, name:str=None) -> None: - super().__init__(name) \ No newline at end of file + + def __init__(self, name: str = None) -> None: + super().__init__(name) From a78542dd8cb06e3b1f6ca2c129ddb89abba0fa2c Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Sun, 8 Oct 2023 18:20:23 -0400 Subject: [PATCH 16/16] black format for tests --- test/test_permeation_problem.py | 15 ++++++++------- test/test_species.py | 7 ++++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/test/test_permeation_problem.py b/test/test_permeation_problem.py index 696cdfb86..3952040da 100644 --- a/test/test_permeation_problem.py +++ b/test/test_permeation_problem.py @@ -27,6 +27,7 @@ import festim as F + def test_permeation_problem(): # mesh nodes vertices = np.linspace(0, 3e-4, num=1001) @@ -46,14 +47,12 @@ def test_permeation_problem(): u_n = mobile_H.prev_solution v = mobile_H.test_function - - temperature = Constant(my_mesh.mesh, 500.) + temperature = Constant(my_mesh.mesh, 500.0) k_B = F.k_B # TODO this should be a property of Mesh n = FacetNormal(my_mesh.mesh) - def siverts_law(T, S_0, E_S, pressure): S = S_0 * exp(-E_S / k_B / T) return S * pressure**0.5 @@ -90,7 +89,6 @@ def siverts_law(T, S_0, E_S, pressure): solver.rtol = 1e-10 solver.atol = 1e10 - solver.report = True ksp = solver.krylov_solver opts = PETSc.Options() @@ -107,7 +105,9 @@ def siverts_law(T, S_0, E_S, pressure): flux_values = [] times = [] t = 0 - progress = tqdm.autonotebook.tqdm(desc="Solving H transport problem", total=final_time) + progress = tqdm.autonotebook.tqdm( + desc="Solving H transport problem", total=final_time + ) while t < final_time: progress.update(float(dt)) t += float(dt) @@ -131,5 +131,6 @@ def siverts_law(T, S_0, E_S, pressure): mobile_xdmf.close() -if __name__=="__main__": - test_permeation_problem() \ No newline at end of file + +if __name__ == "__main__": + test_permeation_problem() diff --git a/test/test_species.py b/test/test_species.py index e81b43e9f..0a194e7ae 100644 --- a/test/test_species.py +++ b/test/test_species.py @@ -9,8 +9,9 @@ def test_assign_functions_to_species(): creates the correct attributes for each species """ - - mesh = F.Mesh1D(vertices=np.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])) + mesh = F.Mesh1D( + vertices=np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) + ) model = F.HydrogenTransportProblem( mesh=mesh, species=[F.Species(name="H"), F.Species(name="Trap")], @@ -24,4 +25,4 @@ def test_assign_functions_to_species(): assert spe.test_function is not None assert isinstance(spe.solution, dolfinx.fem.Function) assert isinstance(spe.prev_solution, dolfinx.fem.Function) - assert isinstance(spe.test_function, ufl.Argument) \ No newline at end of file + assert isinstance(spe.test_function, ufl.Argument)