diff --git a/.github/workflows/run_tests.sh b/.github/workflows/run_tests.sh index 1e86113..8018780 100644 --- a/.github/workflows/run_tests.sh +++ b/.github/workflows/run_tests.sh @@ -20,8 +20,12 @@ conda activate $CONDA_ENV $PYTHON -m unittest discover -v $PYTHON -m unittest discover -v -p 'ptest_*' +mpirun -n 2 --oversubscribe $PYTHON ptest_augmentedVector.py +mpirun -n 2 --oversubscribe $PYTHON ptest_mpiUtils.py mpirun -n 2 --oversubscribe $PYTHON ptest_meanVarRiskMeasureSAA.py mpirun -n 2 --oversubscribe $PYTHON ptest_scipyCostWrapper.py mpirun -n 2 --oversubscribe $PYTHON ptest_superquantileSAA.py mpirun -n 2 --oversubscribe $PYTHON ptest_transformedMeanRiskMeasureSAA.py + + diff --git a/doc/soupy.cost.rst b/doc/soupy.cost.rst new file mode 100644 index 0000000..951a065 --- /dev/null +++ b/doc/soupy.cost.rst @@ -0,0 +1,29 @@ +soupy.cost +========================= + + +soupy.cost.controlCostFunctional +--------------------------------------- + +.. automodule:: soupy.cost.controlCostFunctional + :members: + :undoc-members: + :show-inheritance: + +soupy.cost.controlCostHessian +--------------------------------------- + +.. automodule:: soupy.cost.controlCostHessian + :members: + :undoc-members: + :show-inheritance: + + +soupy.cost.penalization +--------------------------------------- + +.. automodule:: soupy.cost.penalization + :members: + :undoc-members: + :show-inheritance: + diff --git a/doc/soupy.modeling.rst b/doc/soupy.modeling.rst index 33338b0..96d37e6 100644 --- a/doc/soupy.modeling.rst +++ b/doc/soupy.modeling.rst @@ -37,47 +37,6 @@ soupy.modeling.controlModelHessian :show-inheritance: -soupy.modeling.controlCostFunctional ---------------------------------------- - -.. automodule:: soupy.modeling.controlCostFunctional - :members: - :undoc-members: - :show-inheritance: - -soupy.modeling.controlCostHessian ---------------------------------------- - -.. automodule:: soupy.modeling.controlCostHessian - :members: - :undoc-members: - :show-inheritance: - -soupy.modeling.riskMeasure ---------------------------------------- - -.. automodule:: soupy.modeling.riskMeasure - :members: - :undoc-members: - :show-inheritance: - - -soupy.modeling.meanVarRiskMeasureStochastic --------------------------------------------- - -.. automodule:: soupy.modeling.meanVarRiskMeasureStochastic - :members: - :undoc-members: - :show-inheritance: - -soupy.modeling.meanVarRiskMeasureSAA ---------------------------------------- - -.. automodule:: soupy.modeling.meanVarRiskMeasureSAA - :members: - :undoc-members: - :show-inheritance: - soupy.modeling.augmentedVector ------------------------------------------- @@ -87,31 +46,6 @@ soupy.modeling.augmentedVector :undoc-members: :show-inheritance: -soupy.modeling.superquantileRiskMeasureSAA -------------------------------------------- - -.. automodule:: soupy.modeling.superquantileRiskMeasureSAA - :members: - :undoc-members: - :show-inheritance: - -soupy.modeling.transformedMeanRiskMeasureSAA ----------------------------------------------- - -.. automodule:: soupy.modeling.transformedMeanRiskMeasureSAA - :members: - :undoc-members: - :show-inheritance: - -soupy.modeling.penalization ---------------------------------------- - -.. automodule:: soupy.modeling.penalization - :members: - :undoc-members: - :show-inheritance: - - soupy.modeling.variables ------------------------------------------- diff --git a/doc/soupy.risk.rst b/doc/soupy.risk.rst new file mode 100644 index 0000000..7601a8f --- /dev/null +++ b/doc/soupy.risk.rst @@ -0,0 +1,43 @@ +soupy.risk +========================= + +soupy.risk.riskMeasure +--------------------------------------- + +.. automodule:: soupy.risk.riskMeasure + :members: + :undoc-members: + :show-inheritance: + + +soupy.risk.meanVarRiskMeasureStochastic +-------------------------------------------- + +.. automodule:: soupy.risk.meanVarRiskMeasureStochastic + :members: + :undoc-members: + :show-inheritance: + +soupy.risk.meanVarRiskMeasureSAA +--------------------------------------- + +.. automodule:: soupy.risk.meanVarRiskMeasureSAA + :members: + :undoc-members: + :show-inheritance: + +soupy.risk.superquantileRiskMeasureSAA +------------------------------------------- + +.. automodule:: soupy.risk.superquantileRiskMeasureSAA + :members: + :undoc-members: + :show-inheritance: + +soupy.risk.transformedMeanRiskMeasureSAA +---------------------------------------------- + +.. automodule:: soupy.risk.transformedMeanRiskMeasureSAA + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/doc/soupy.rst b/doc/soupy.rst index acf2423..6444b95 100644 --- a/doc/soupy.rst +++ b/doc/soupy.rst @@ -7,6 +7,8 @@ Submodules .. toctree:: soupy.modeling + soupy.risk + soupy.cost soupy.optimization soupy.solver soupy.collectives diff --git a/soupy/__init__.py b/soupy/__init__.py index 1af7b6a..f4ef23b 100644 --- a/soupy/__init__.py +++ b/soupy/__init__.py @@ -13,10 +13,14 @@ from .collectives import * +from .cost import * + from .modeling import * from .optimization import * +from .risk import * + from .solver import * from .utils import * diff --git a/soupy/collectives/mpiUtils.py b/soupy/collectives/mpiUtils.py index f0cf399..3e9c2ab 100644 --- a/soupy/collectives/mpiUtils.py +++ b/soupy/collectives/mpiUtils.py @@ -13,6 +13,7 @@ import numpy as np from mpi4py import MPI +from ..modeling.augmentedVector import AugmentedVector def allocate_process_sample_sizes(sample_size, comm_sampler): """ @@ -63,11 +64,23 @@ def set_local_from_global(v, v_np): :param v_np: numpy array for global entries :type v_np: np.ndarray """ - - local_range = v.local_range() - if len(local_range) > 0: - v.set_local(v_np[local_range[0] : local_range[1]]) - v.apply("") + + if isinstance(v, AugmentedVector): + # Set the vector component + local_range = v.get_vector().local_range() + if len(local_range) > 0: + v.get_vector().set_local(v_np[local_range[0] : local_range[1]]) + v.apply("") + + # Set the scalar component + v.set_scalar(v_np[-1]) + else: + local_range = v.local_range() + if len(local_range) > 0: + v.set_local(v_np[local_range[0] : local_range[1]]) + v.apply("") + + def get_global(v): """ diff --git a/soupy/cost/__init__.py b/soupy/cost/__init__.py new file mode 100644 index 0000000..411116a --- /dev/null +++ b/soupy/cost/__init__.py @@ -0,0 +1,5 @@ +from .controlCostFunctional import ControlCostFunctional, DeterministicControlCostFunctional, RiskMeasureControlCostFunctional, PenalizationControlCostFunctional + +from .controlCostHessian import ControlCostHessian + +from .penalization import Penalization, L2Penalization, WeightedL2Penalization, MultiPenalization, VariationalPenalization diff --git a/soupy/modeling/controlCostFunctional.py b/soupy/cost/controlCostFunctional.py similarity index 99% rename from soupy/modeling/controlCostFunctional.py rename to soupy/cost/controlCostFunctional.py index bdb04dd..a707b47 100644 --- a/soupy/modeling/controlCostFunctional.py +++ b/soupy/cost/controlCostFunctional.py @@ -15,8 +15,7 @@ import numpy as np import dolfin as dl -from .variables import STATE, PARAMETER, ADJOINT, CONTROL -from .augmentedVector import AugmentedVector +from ..modeling import STATE, PARAMETER, ADJOINT, CONTROL, AugmentedVector class ControlCostFunctional: """ diff --git a/soupy/modeling/controlCostHessian.py b/soupy/cost/controlCostHessian.py similarity index 97% rename from soupy/modeling/controlCostHessian.py rename to soupy/cost/controlCostHessian.py index 362cffc..ef71eec 100644 --- a/soupy/modeling/controlCostHessian.py +++ b/soupy/cost/controlCostHessian.py @@ -12,7 +12,7 @@ # Software Foundation) version 3.0 dated June 2007. -from .variables import STATE, ADJOINT, PARAMETER, CONTROL +from ..modeling import STATE, ADJOINT, PARAMETER, CONTROL class ControlCostHessian: """ diff --git a/soupy/modeling/penalization.py b/soupy/cost/penalization.py similarity index 99% rename from soupy/modeling/penalization.py rename to soupy/cost/penalization.py index 492bd1e..9488c57 100644 --- a/soupy/modeling/penalization.py +++ b/soupy/cost/penalization.py @@ -12,8 +12,7 @@ # Software Foundation) version 3.0 dated June 2007. import dolfin as dl -from .variables import STATE, CONTROL -from .augmentedVector import AugmentedVector +from ..modeling import STATE, CONTROL, AugmentedVector class Penalization: diff --git a/soupy/modeling/__init__.py b/soupy/modeling/__init__.py index 5d62252..4d427f3 100644 --- a/soupy/modeling/__init__.py +++ b/soupy/modeling/__init__.py @@ -15,29 +15,11 @@ from .augmentedVector import AugmentedVector -from .controlCostFunctional import ControlCostFunctional, DeterministicControlCostFunctional, RiskMeasureControlCostFunctional, PenalizationControlCostFunctional - -from .controlCostHessian import ControlCostHessian - from .controlModel import ControlModel from .controlModelHessian import ControlModelHessian from .controlQoI import ControlQoI, L2MisfitVarfHandler, VariationalControlQoI, L2MisfitControlQoI -from .meanVarRiskMeasureStochastic import meanVarRiskMeasureStochasticSettings, MeanVarRiskMeasureStochastic - -from .meanVarRiskMeasureSAA import meanVarRiskMeasureSAASettings, MeanVarRiskMeasureSAA - -from .penalization import Penalization, L2Penalization, WeightedL2Penalization, MultiPenalization, VariationalPenalization - -from .riskMeasure import RiskMeasure - -from .smoothPlusApproximation import SmoothPlusApproximationQuartic, SmoothPlusApproximationSoftplus - -from .superquantileRiskMeasureSAA import SuperquantileRiskMeasureSAA, superquantileRiskMeasureSAASettings, sample_superquantile, sample_superquantile_by_minimization - -from .transformedMeanRiskMeasureSAA import TransformedMeanRiskMeasureSAA, transformedMeanRiskMeasureSAASettings, IdentityFunction, FunctionWrapper - from .variables import STATE, PARAMETER, ADJOINT, CONTROL diff --git a/soupy/modeling/augmentedVector.py b/soupy/modeling/augmentedVector.py index dfcc4fc..9365332 100644 --- a/soupy/modeling/augmentedVector.py +++ b/soupy/modeling/augmentedVector.py @@ -28,7 +28,8 @@ def __init__(self, v, copy_vector=True): :param v: :code:`dolfin.Vector` to be augmented :param copy_vector: If :code:`True`, copy the vector, otherwise use the same memory """ - assert v.mpi_comm().Get_size() == 1 + # assert v.mpi_comm().Get_size() == 1 # Working towards removing this constraint + self._mpi_comm = v.mpi_comm() if copy_vector: self.v = v.copy() else: @@ -40,7 +41,9 @@ def copy(self): x = AugmentedVector(self.v, copy_vector=True) x.set_scalar(self.t) - + def mpi_comm(self): + return self._mpi_comm + def add_local(self, vt_array): self.v.add_local(vt_array[:-1]) self.v.apply("") @@ -51,9 +54,6 @@ def set_local(self, vt_array): self.v.apply("") self.t = vt_array[-1] - def apply(self, method): - self.v.apply(method) - def get_local(self): return np.append(self.v.get_local(), self.t) @@ -84,4 +84,14 @@ def inner(self, vt): def apply(self, method): self.v.apply(method) + + def gather_on_zero(self): + v_np = self.v.gather_on_zero() + if self._mpi_comm.Get_rank() == 0: + v_np = np.append(v_np, self.t) + return v_np + + + def size(self): + return self.v.size() + 1 diff --git a/soupy/optimization/inexactNewtonCG.py b/soupy/optimization/inexactNewtonCG.py index f40541d..d84969c 100644 --- a/soupy/optimization/inexactNewtonCG.py +++ b/soupy/optimization/inexactNewtonCG.py @@ -16,7 +16,7 @@ from hippylib import ParameterList -from ..modeling.controlCostHessian import ControlCostHessian +from ..cost.controlCostHessian import ControlCostHessian from ..modeling.variables import CONTROL from .cgSolverSteihaug import CGSolverSteihaug diff --git a/soupy/risk/__init__.py b/soupy/risk/__init__.py new file mode 100644 index 0000000..4789779 --- /dev/null +++ b/soupy/risk/__init__.py @@ -0,0 +1,12 @@ +from .meanVarRiskMeasureStochastic import meanVarRiskMeasureStochasticSettings, MeanVarRiskMeasureStochastic + +from .meanVarRiskMeasureSAA import meanVarRiskMeasureSAASettings, MeanVarRiskMeasureSAA + +from .riskMeasure import RiskMeasure + +from .smoothPlusApproximation import SmoothPlusApproximationQuartic, SmoothPlusApproximationSoftplus + +from .superquantileRiskMeasureSAA import SuperquantileRiskMeasureSAA, superquantileRiskMeasureSAASettings, sample_superquantile, sample_superquantile_by_minimization + +from .transformedMeanRiskMeasureSAA import TransformedMeanRiskMeasureSAA, transformedMeanRiskMeasureSAASettings, IdentityFunction, FunctionWrapper + diff --git a/soupy/modeling/meanVarRiskMeasureSAA.py b/soupy/risk/meanVarRiskMeasureSAA.py similarity index 99% rename from soupy/modeling/meanVarRiskMeasureSAA.py rename to soupy/risk/meanVarRiskMeasureSAA.py index 955afb4..8516875 100644 --- a/soupy/modeling/meanVarRiskMeasureSAA.py +++ b/soupy/risk/meanVarRiskMeasureSAA.py @@ -20,8 +20,7 @@ from hippylib import ParameterList, Random from .riskMeasure import RiskMeasure -from .variables import STATE, PARAMETER, ADJOINT, CONTROL -from .controlModelHessian import ControlModelHessian +from ..modeling import STATE, PARAMETER, ADJOINT, CONTROL, ControlModelHessian from ..collectives import NullCollective, MultipleSamePartitioningPDEsCollective, \ MultipleSerialPDEsCollective, allocate_process_sample_sizes diff --git a/soupy/modeling/meanVarRiskMeasureStochastic.py b/soupy/risk/meanVarRiskMeasureStochastic.py similarity index 98% rename from soupy/modeling/meanVarRiskMeasureStochastic.py rename to soupy/risk/meanVarRiskMeasureStochastic.py index ed8b6a0..15a70f3 100644 --- a/soupy/modeling/meanVarRiskMeasureStochastic.py +++ b/soupy/risk/meanVarRiskMeasureStochastic.py @@ -20,7 +20,7 @@ from .riskMeasure import RiskMeasure -from .variables import STATE, PARAMETER, ADJOINT, CONTROL +from ..modeling import STATE, PARAMETER, ADJOINT, CONTROL def meanVarRiskMeasureStochasticSettings(data = {}): diff --git a/soupy/modeling/riskMeasure.py b/soupy/risk/riskMeasure.py similarity index 100% rename from soupy/modeling/riskMeasure.py rename to soupy/risk/riskMeasure.py diff --git a/soupy/modeling/smoothPlusApproximation.py b/soupy/risk/smoothPlusApproximation.py similarity index 100% rename from soupy/modeling/smoothPlusApproximation.py rename to soupy/risk/smoothPlusApproximation.py diff --git a/soupy/modeling/superquantileRiskMeasureSAA.py b/soupy/risk/superquantileRiskMeasureSAA.py similarity index 98% rename from soupy/modeling/superquantileRiskMeasureSAA.py rename to soupy/risk/superquantileRiskMeasureSAA.py index b7b2fad..2f844b3 100644 --- a/soupy/modeling/superquantileRiskMeasureSAA.py +++ b/soupy/risk/superquantileRiskMeasureSAA.py @@ -20,13 +20,12 @@ from hippylib import ParameterList, Random from .riskMeasure import RiskMeasure -from .variables import STATE, PARAMETER, ADJOINT, CONTROL -from .controlModelHessian import ControlModelHessian + +from ..modeling import STATE, PARAMETER, ADJOINT, CONTROL, ControlModelHessian, AugmentedVector from ..collectives import NullCollective, MultipleSamePartitioningPDEsCollective, \ MultipleSerialPDEsCollective, allocate_process_sample_sizes from .smoothPlusApproximation import SmoothPlusApproximationQuartic, SmoothPlusApproximationSoftplus -from .augmentedVector import AugmentedVector diff --git a/soupy/modeling/transformedMeanRiskMeasureSAA.py b/soupy/risk/transformedMeanRiskMeasureSAA.py similarity index 99% rename from soupy/modeling/transformedMeanRiskMeasureSAA.py rename to soupy/risk/transformedMeanRiskMeasureSAA.py index f771887..bb1a0a5 100644 --- a/soupy/modeling/transformedMeanRiskMeasureSAA.py +++ b/soupy/risk/transformedMeanRiskMeasureSAA.py @@ -20,9 +20,7 @@ from hippylib import ParameterList, Random from .riskMeasure import RiskMeasure -from .variables import STATE, PARAMETER, ADJOINT, CONTROL -from .controlModelHessian import ControlModelHessian - +from ..modeling import STATE, PARAMETER, ADJOINT, CONTROL, ControlModelHessian from ..collectives import NullCollective, MultipleSamePartitioningPDEsCollective, \ MultipleSerialPDEsCollective, allocate_process_sample_sizes diff --git a/soupy/test/ptest_augmentedVector.py b/soupy/test/ptest_augmentedVector.py new file mode 100644 index 0000000..820e72c --- /dev/null +++ b/soupy/test/ptest_augmentedVector.py @@ -0,0 +1,107 @@ +# Copyright (c) 2023, The University of Texas at Austin +# & Georgia Institute of Technology +# +# All Rights reserved. +# See file COPYRIGHT for details. +# +# This file is part of the SOUPy package. For more information see +# https://github.com/hippylib/soupy/ +# +# SOUPy is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License (as published by the Free +# Software Foundation) version 3.0 dated June 2007. + +import unittest +import dolfin as dl +import numpy as np + +import sys +import os + +sys.path.append(os.environ.get('HIPPYLIB_PATH')) +sys.path.append('../../') +from soupy import AugmentedVector, set_local_from_global + +class TestAugmentedVectorMeshParallel(unittest.TestCase): + """ + Test cases for :code:`AugmentedVector` in the case where + mesh is partitioned in MPI + """ + def setUp(self): + mesh = dl.UnitIntervalMesh(10) + self.V = dl.FunctionSpace(mesh, "CG", 2) + self.dim = self.V.dim() + self.atol = 1e-6 + + def _construct_test_vector(self, copy_vector=False): + z_fun = dl.Function(self.V) + z_fun.interpolate(dl.Expression("sin(x[0])", degree=4)) + + z = z_fun.vector() + zt = AugmentedVector(z, copy_vector=copy_vector) + return z, zt + + def testConstructor(self): + """ + Check that each process gets the partitioned vector :code:`z` + and the full scalar :code:`t` + """ + z, zt = self._construct_test_vector() + t_true = 2.0 + zt.set_scalar(t_true) + + z_get = zt.get_vector() + t_get = zt.get_scalar() + + + z_diff = z - z_get + z_diff_norm = np.sqrt(z_diff.inner(z_diff)) + self.assertTrue(z_diff_norm <= self.atol) + + self.assertTrue(np.isclose(t_get, t_true)) + + def testGetLocal(self): + """ + Test that :code:`AugmentedVector.get_local()` + retrieves a local vector that contains the underlying + vector :code:`v.get_local()` concatenated to the scalar :code:`t` + i.e. it should be :code:`[v_local, t]` + """ + z, zt = self._construct_test_vector(copy_vector=False) + t = 2.0 + zt.set_scalar(t) + + z_get = zt.get_vector() + + # Check local objects are correct + z_local = z.get_local() + zt_local = zt.get_local() + + self.assertTrue(len(zt_local) == len(z_local) + 1) + self.assertTrue(np.allclose(z_local, zt_local[:-1])) + self.assertTrue(np.isclose(zt_local[-1], t)) + + def testInner(self): + """ + Test the inner product :code:`AugmentedVector.inner(v_other)` + Uses :code:`set_local_from_global()` which is tested in another + test case under :code:`ptest_mpiUtils.py` + """ + z1 = dl.Function(self.V).vector() + z2 = dl.Function(self.V).vector() + + # Need to fix seed to ensure each process gets the same + zt1_np = np.arange(self.dim+1) + zt2_np = np.arange(self.dim+1) / 2 + zt1 = AugmentedVector(z1) + zt2 = AugmentedVector(z2) + set_local_from_global(zt1, zt1_np) + set_local_from_global(zt2, zt2_np) + + ip = zt1.inner(zt2) + self.assertTrue(np.allclose([ip], [np.inner(zt1_np, zt2_np)])) + + +if __name__ == "__main__": + unittest.main() + diff --git a/soupy/test/ptest_mpiUtils.py b/soupy/test/ptest_mpiUtils.py new file mode 100644 index 0000000..bcd6e56 --- /dev/null +++ b/soupy/test/ptest_mpiUtils.py @@ -0,0 +1,153 @@ +# Copyright (c) 2023, The University of Texas at Austin +# & Georgia Institute of Technology +# +# All Rights reserved. +# See file COPYRIGHT for details. +# +# This file is part of the SOUPy package. For more information see +# https://github.com/hippylib/soupy/ +# +# SOUPy is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License (as published by the Free +# Software Foundation) version 3.0 dated June 2007. + +import unittest +import dolfin as dl +import numpy as np + +import sys +import os +from mpi4py import MPI + +sys.path.append(os.environ.get('HIPPYLIB_PATH')) +sys.path.append('../../') +from soupy import AugmentedVector, set_local_from_global, get_global + +class TestParallelGetSet(unittest.TestCase): + def setUp(self): + self.comm = MPI.COMM_WORLD + self.mesh = dl.UnitIntervalMesh(self.comm, 10) + self.V = dl.FunctionSpace(self.mesh, "CG", 2) + self.dim = self.V.dim() + self.atol = 1e-6 + self.comm_size = self.comm.Get_size() + self.comm_rank = self.comm.Get_rank() + + def _construct_test_vector(self): + z_fun = dl.Function(self.V) + z_fun.interpolate(dl.Expression("sin(x[0])", degree=4)) + return z_fun.vector() + + def testVectorGetGlobal(self): + """ + Check that all processes using get_global get the gathered case + Uses numpy i/o to check mpi comm + """ + z = self._construct_test_vector() + z_np = get_global(z) + + # Get the gathered form of original vector as ground truth + z_gathered_on_zero = z.gather_on_zero() + if self.comm_rank == 0: + np.save(f"temp_z.npy", z_gathered_on_zero) + self.comm.Barrier() + + # Load in ground truth on all of the processes and compare + z_gathered_on_zero = np.load(f"temp_z.npy") + self.assertTrue(np.allclose(z_gathered_on_zero, z_np)) + + # Clean up + if self.comm_rank == 0: + os.system("rm temp_z.npy") + self.comm.Barrier() + + + + def testVectorSetGlobal(self): + """ + Check that all processes using get_global get the gathered case + Uses numpy i/o to check mpi comm + """ + z = self._construct_test_vector() + z_np = get_global(z) + + # Completely zeroed vector + z_new = dl.Function(self.V).vector() + set_local_from_global(z_new, z_np) + + z_diff = z - z_new + z_diff_norm = np.sqrt(z_diff.inner(z_diff)) + self.assertTrue(z_diff_norm <= self.atol) + + + + + def testAugmentedVectorGetGlobal(self): + """ + Check that all processes using set_global properly sets the gathered vector + """ + z = self._construct_test_vector() + zt = AugmentedVector(z) + t = 2.8 + zt.set_scalar(t) + + + # Get the global from function + zt_np = get_global(zt) + z_np = zt_np[:-1] + t_np = zt_np[-1] + + # Get the gathered form of original vector as ground truth + z_gathered_on_zero = z.gather_on_zero() + if self.comm_rank == 0: + np.save(f"temp_z.npy", z_gathered_on_zero) + self.comm.Barrier() + + # Load in ground truth on all of the processes + z_gathered_on_zero = np.load(f"temp_z.npy") + + # Compare the vector components + self.assertTrue(np.allclose(z_gathered_on_zero, z_np)) + + # Compare the global scalar to true scalar + self.assertTrue(t == t_np) + + # Clean up + if self.comm_rank == 0: + os.system("rm temp_z.npy") + self.comm.Barrier() + + + + def testAugmentedVectorSetGlobal(self): + """ + Check that all processes using set_global properly sets the gathered vector + """ + z = self._construct_test_vector() + t = -2.8 + zt = AugmentedVector(z) + zt.set_scalar(t) + + + zt_np = get_global(zt) + + # Completely zeroed vector + z_new = dl.Function(self.V).vector() + zt_new = AugmentedVector(z_new) + set_local_from_global(zt_new, zt_np) + + # pull out internals + z_new = zt_new.get_vector() + t_new = zt_new.get_scalar() + + # Check vector difference + z_diff = z - z_new + z_diff_norm = np.sqrt(z_diff.inner(z_diff)) + self.assertTrue(z_diff_norm <= self.atol) + + # Check scalar difference + self.assertTrue(np.abs(t - t_new)< self.atol) + + +if __name__ == "__main__": + unittest.main() diff --git a/soupy/version.py b/soupy/version.py index d71d968..f064ec6 100644 --- a/soupy/version.py +++ b/soupy/version.py @@ -11,5 +11,5 @@ # terms of the GNU General Public License (as published by the Free # Software Foundation) version 3.0 dated June 2007. -version_info = (1, 0, 0) +version_info = (1, 1, 0) __version__ = '.'.join([str(x) for x in version_info])