Repository: CUQI-DTU/CUQIpy-FEniCS (language: python)

Issue:
Update fenics plug in to reflect updates in cuqipy
- [ ] Fix imports in files and demos
- [ ] Define par_dim for geometry and update the library files and demo to use that
- [ ] Update how test problems are defined
- [ ] Turn off logging



Discussion / hints:

Fix patch:
diff --git a/cuqipy-fenics/__init__.py b/cuqipy_fenics/__init__.py
similarity index 59%
rename from cuqipy-fenics/__init__.py
rename to cuqipy_fenics/__init__.py
index 5aca598..2145193 100644
--- a/cuqipy-fenics/__init__.py
+++ b/cuqipy_fenics/__init__.py
@@ -1,3 +1,6 @@
 from . import pde
 from . import geometry
 from . import testproblem
+
+import dolfin as dl
+dl.set_log_active(False)
diff --git a/cuqipy-fenics/geometry.py b/cuqipy_fenics/geometry.py
similarity index 98%
rename from cuqipy-fenics/geometry.py
rename to cuqipy_fenics/geometry.py
index c9dd346..822500d 100644
--- a/cuqipy-fenics/geometry.py
+++ b/cuqipy_fenics/geometry.py
@@ -27,7 +27,7 @@ def mesh(self):
         return self.function_space.mesh()
 
     @property
-    def shape(self):
+    def par_shape(self):
         return (self.function_space.dim(),)
 
     def par2fun(self,par):
@@ -176,7 +176,7 @@ def __init__(self, geometry, length_scale, num_terms):
         self._eig_vec = None
 
     @property
-    def shape(self):
+    def par_shape(self):
         return (self.num_terms,)
 
     @property
@@ -219,7 +219,7 @@ def par2field(self, p):
 	   
         p = self._process_values(p)
         Ns = p.shape[-1]
-        field_list = np.empty((self.geometry.dim,Ns))
+        field_list = np.empty((self.geometry.par_dim,Ns))
 
         for idx in range(Ns):
             field_list[:,idx] = self.eig_vec@( np.sqrt(self.eig_val)*p[...,idx] )
@@ -260,4 +260,4 @@ def _build_space(self):
         else:
             raise NotImplementedError
 
-        return V
\ No newline at end of file
+        return V
diff --git a/cuqipy-fenics/pde.py b/cuqipy_fenics/pde.py
similarity index 97%
rename from cuqipy-fenics/pde.py
rename to cuqipy_fenics/pde.py
index cc4e443..f0d9d03 100644
--- a/cuqipy-fenics/pde.py
+++ b/cuqipy_fenics/pde.py
@@ -1,7 +1,7 @@
 import numpy as np
 from abc import ABC, abstractmethod
-from ..pde import PDE
-from ..samples import CUQIarray
+from cuqi.pde import PDE
+from cuqi.samples import CUQIarray
 import dolfin as dl
 import ufl
 
@@ -94,4 +94,4 @@ def _create_observation_operator(self, observation_operator):
             observation_operator = observation_operator
         else:
             raise NotImplementedError
-        return observation_operator
\ No newline at end of file
+        return observation_operator
diff --git a/demos/demo01_1D_Diffusion.ipynb b/demos/demo01_1D_Diffusion.ipynb
index 40ef396..c95f8f9 100644
--- a/demos/demo01_1D_Diffusion.ipynb
+++ b/demos/demo01_1D_Diffusion.ipynb
@@ -88,8 +88,9 @@
     "import sys\n",
     "import numpy as np\n",
     "import matplotlib.pyplot as plt\n",
-    "sys.path.append(\"../../\")\n",
-    "import cuqi"
+    "sys.path.append(\"../\")\n",
+    "import cuqi\n",
+    "import cuqipy_fenics"
    ]
   },
   {
@@ -135,7 +136,7 @@
    "outputs": [],
    "source": [
     "model, data, problemInfo = \\\n",
-    "    cuqi.fenics.testproblem.FEniCSDiffusion1D.get_components(dim=dim,\\\n",
+    "    cuqipy_fenics.testproblem.FEniCSDiffusion1D.get_components(dim=dim,\\\n",
     "                                                             exactSolution=myExactSolution,\\\n",
     "                                                             observation_operator=observation_operator,\\\n",
     "                                                             SNR=SNR,\\\n",
@@ -388,7 +389,7 @@
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "Python 3",
+   "display_name": "Python 3.10.5 ('fenicsproject')",
    "language": "python",
    "name": "python3"
   },
@@ -402,7 +403,12 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.6.9"
+   "version": "3.10.5"
+  },
+  "vscode": {
+   "interpreter": {
+    "hash": "f83c72a7c5d885a4a7f43561cb77434137f6f5cf21a7418d4732e18616218db3"
+   }
   }
  },
  "nbformat": 4,
diff --git a/demos/demo01_1D_Diffusion.py b/demos/demo01_1D_Diffusion.py
index d5c2e09..3560a03 100644
--- a/demos/demo01_1D_Diffusion.py
+++ b/demos/demo01_1D_Diffusion.py
@@ -3,8 +3,9 @@
 import sys
 import numpy as np
 import matplotlib.pyplot as plt
-sys.path.append("../../")
 import cuqi
+sys.path.append('../')
+import cuqipy_fenics
 
 np.random.seed(0)
 mapping =  'exponential'
@@ -16,7 +17,7 @@
 #%%
 observation_operator=None
 SNR = 1000
-model, data, problemInfo = cuqi.fenics.testproblem.FEniCSDiffusion1D.get_components(dim = dim, exactSolution = myExactSolution, observation_operator=observation_operator , SNR = SNR, mapping = mapping, left_bc = 1, right_bc = 8, endpoint=L)
+model, data, problemInfo = cuqipy_fenics.testproblem.FEniCSDiffusion1D.get_components(dim = dim, exactSolution = myExactSolution, observation_operator=observation_operator , SNR = SNR, mapping = mapping, left_bc = 1, right_bc = 8, endpoint=L)
 
 model.range_geometry.plot(data)
 plt.title('Data')
diff --git a/demos/demo02_Matern.py b/demos/demo02_Matern.py
index cec38a1..9245727 100644
--- a/demos/demo02_Matern.py
+++ b/demos/demo02_Matern.py
@@ -2,8 +2,8 @@
 import sys
 import numpy as np
 import matplotlib.pyplot as plt
-sys.path.append("../../")
-from cuqi.fenics.geometry import MaternExpansion, FEniCSContinuous
+sys.path.append("../")
+from cuqipy_fenics.geometry import MaternExpansion, FEniCSContinuous
 from cuqi.distribution import GaussianCov
 import dolfin as dl
 
@@ -14,8 +14,8 @@
                                 length_scale = .2,
                                 num_terms=128)
 
-MaternField = GaussianCov(np.zeros(MaternGeometry.dim),
-                cov=np.eye(MaternGeometry.dim),
+MaternField = GaussianCov(np.zeros(MaternGeometry.par_dim),
+                cov=np.eye(MaternGeometry.par_dim),
                 geometry= MaternGeometry)
 
 samples = MaternField.sample()
@@ -26,4 +26,4 @@
     plt.figure()
     geometry.plot(MaternGeometry.eig_vec[:,i]) 
     plt.show()
-    plt.close('all')
\ No newline at end of file
+    plt.close('all')
diff --git a/demos/demo03_poisson_circular.py b/demos/demo03_poisson_circular.py
index 717e875..c81f6a3 100644
--- a/demos/demo03_poisson_circular.py
+++ b/demos/demo03_poisson_circular.py
@@ -2,7 +2,8 @@
 import dolfin as dl
 import sys
 import numpy as np
-sys.path.append("../../")
+sys.path.append("../")
+import cuqipy_fenics
 import cuqi
 import mshr
 import matplotlib.pyplot as plt
@@ -58,11 +59,11 @@ def u_boundary(x, on_boundary):
 #%% 2.1 Create the domain geometry 
 
 # 2.1.1 The space on which the Bayesian parameters are defined
-fenics_continuous_geo = cuqi.fenics.geometry.FEniCSContinuous(parameter_space)
+fenics_continuous_geo = cuqipy_fenics.geometry.FEniCSContinuous(parameter_space)
 
 # 2.1.2 The Matern fieled (maps i.i.d normal random vector of dimension `num_terms`
 # to Matern field realization on `fenics_continuous_geo`)
-matern_geo = cuqi.fenics.geometry.MaternExpansion(fenics_continuous_geo, length_scale = .8, num_terms=128)
+matern_geo = cuqipy_fenics.geometry.MaternExpansion(fenics_continuous_geo, length_scale = .8, num_terms=128)
 
 # 2.1.3 We create a map `heavy_map` to map the Matern field realization to two levels
 # c_minus and c_plus 
@@ -76,21 +77,21 @@ def heavy_map(func):
 
 # 2.1.4 Finally, we create the domain geometry which applies the
 # map `heavy_map` on Matern realizations.
-domain_geometry = cuqi.fenics.geometry.FEniCSMappedGeometry(matern_geo, map = heavy_map)
+domain_geometry = cuqipy_fenics.geometry.FEniCSMappedGeometry(matern_geo, map = heavy_map)
 
 #%% 2.2 Create the range geomtry 
-range_geometry = cuqi.fenics.geometry.FEniCSContinuous(solution_space) 
+range_geometry = cuqipy_fenics.geometry.FEniCSContinuous(solution_space) 
 
 #%% 2.3 Create CUQI PDE (which encapsulates the FEniCS formulation
 # of the PDE)
-PDE = cuqi.fenics.pde.SteadyStateLinearFEniCSPDE( form, mesh, solution_space, parameter_space,dirichlet_bc, observation_operator=obs_func)
+PDE = cuqipy_fenics.pde.SteadyStateLinearFEniCSPDE( form, mesh, solution_space, parameter_space,dirichlet_bc, observation_operator=obs_func)
 
 #%% 2.4 Create CUQI model
 model = cuqi.model.PDEModel(PDE,range_geometry,domain_geometry)
 
 #%% 2.5 Create a prior
-pr_mean = np.zeros(domain_geometry.dim)
-prior = cuqi.distribution.GaussianCov(pr_mean, cov=np.eye(domain_geometry.dim), geometry= domain_geometry)
+pr_mean = np.zeros(domain_geometry.par_dim)
+prior = cuqi.distribution.GaussianCov(pr_mean, cov=np.eye(domain_geometry.par_dim), geometry= domain_geometry)
 
 #%% 2.6 Define the exact solution
 exactSolution = prior.sample()
@@ -102,7 +103,7 @@ def heavy_map(func):
 SNR = 100
 sigma = np.linalg.norm(b_exact)/SNR
 sigma2 = sigma*sigma # variance of the observation Gaussian noise
-data_distribution = cuqi.distribution.GaussianCov(model, sigma2*np.ones(range_geometry.dim), geometry=range_geometry)
+data_distribution = cuqi.distribution.GaussianCov(model, sigma2*np.ones(range_geometry.par_dim), geometry=range_geometry)
 
 #%% 2.9 Generate noisy data
 data = data_distribution(x=exactSolution).sample()
diff --git a/demos/try01_FenicsGeometry.py b/demos/try01_FenicsGeometry.py
index 3f3c8c0..f1744fb 100644
--- a/demos/try01_FenicsGeometry.py
+++ b/demos/try01_FenicsGeometry.py
@@ -1,8 +1,8 @@
 
 #%%
 import sys
-sys.path.append("../../")
-import cuqi
+sys.path.append("../")
+import cuqipy_fenics
 import matplotlib.pyplot as plt
 import numpy as np
 import warnings
@@ -16,7 +16,7 @@
 # Define FenicsContinuous2D object 
 mesh1 = dl.UnitIntervalMesh(30)
 Vh1 = dl.FunctionSpace(mesh1, 'CG', 1)
-geom1 = cuqi.fenics.geometry.FEniCSContinuous(Vh1)
+geom1 = cuqipy_fenics.geometry.FEniCSContinuous(Vh1)
 
 # Define function
 f1= dl.Function(Vh1)
@@ -33,7 +33,7 @@
 # Define FenicsContinuous2D object 
 mesh = dl.UnitSquareMesh(10,10)
 Vh = dl.FunctionSpace(mesh, 'CG', 1)
-geom = cuqi.fenics.geometry.FEniCSContinuous(Vh)
+geom = cuqipy_fenics.geometry.FEniCSContinuous(Vh)
 
 # Define function
 f1= dl.Function(Vh)


Test patch:
diff --git a/cuqipy-fenics/testproblem.py b/cuqipy_fenics/testproblem.py
similarity index 84%
rename from cuqipy-fenics/testproblem.py
rename to cuqipy_fenics/testproblem.py
index d72c084..282b772 100644
--- a/cuqipy-fenics/testproblem.py
+++ b/cuqipy_fenics/testproblem.py
@@ -1,7 +1,8 @@
 import sys
 import numpy as np
 import matplotlib.pyplot as plt
-sys.path.append("../../")
+sys.path.append("../")
+import cuqipy_fenics
 import dolfin as dl
 import warnings
 import cuqi
@@ -85,10 +86,10 @@ def form(m,u,p):
         dirichlet_bc_expression = dl.Expression("left_bc*(x[0]<eps)+right_bc*(x[0]>endpoint-eps)", eps=dl.DOLFIN_EPS, endpoint=endpoint, left_bc=left_bc, right_bc=right_bc, degree=1)
         dirichlet_bc = dl.DirichletBC(solution_function_space, dirichlet_bc_expression, u_boundary)
 
-        PDE = cuqi.fenics.pde.SteadyStateLinearFEniCSPDE( form, mesh, solution_function_space, parameter_function_space, dirichlet_bc,observation_operator=observation_operator)
+        PDE = cuqipy_fenics.pde.SteadyStateLinearFEniCSPDE( form, mesh, solution_function_space, parameter_function_space, dirichlet_bc,observation_operator=observation_operator)
         
         # Create PDE model
-        domain_geometry = cuqi.fenics.geometry.FEniCSContinuous(parameter_function_space)
+        domain_geometry = cuqipy_fenics.geometry.FEniCSContinuous(parameter_function_space)
         if mapping is not None:
             if mapping == 'exponential':
                 mapping = lambda x : ufl.exp(x)
@@ -96,15 +97,15 @@ def form(m,u,p):
                 mapping = mapping
             else:
                 raise ValueError('mapping can be a function or one of the expected keywords.')
-            domain_geometry =  cuqi.fenics.geometry.FEniCSMappedGeometry(geometry=domain_geometry, map = mapping)
+            domain_geometry =  cuqipy_fenics.geometry.FEniCSMappedGeometry(geometry=domain_geometry, map = mapping)
 
-        range_geometry = cuqi.fenics.geometry.FEniCSContinuous(solution_function_space)
+        range_geometry = cuqipy_fenics.geometry.FEniCSContinuous(solution_function_space)
         
         model = cuqi.model.PDEModel(PDE,range_geometry,domain_geometry)
 
         # Create prior
-        pr_mean = np.zeros(domain_geometry.dim)
-        prior = cuqi.distribution.GMRF(pr_mean,25,1,'zero') 
+        pr_mean = np.zeros(domain_geometry.par_dim)
+        x = cuqi.distribution.GMRF(pr_mean,25,1,'zero') 
         
         # Set up exact solution
         if exactSolution is None:
@@ -125,10 +126,10 @@ def form(m,u,p):
         data = b_exact + np.random.normal( 0, sigma, b_exact.shape )
         
         # Create likelihood
-        likelihood = cuqi.distribution.GaussianCov(model, sigma2*np.eye(range_geometry.dim)).to_likelihood(data)
+        y = cuqi.distribution.GaussianCov(model(x), sigma2*np.eye(range_geometry.par_dim))
 
         # Initialize FEniCSDiffusion1D as BayesianProblem problem
-        super().__init__(likelihood, prior)
+        super().__init__(y, x, y=data)
 
         # Store exact values and information
         self.exactSolution = exactSolution