def test_2ministep(self):
        with ErtTestContext("row_scaling", self.config_file) as tc:
            main = tc.getErt()
            init_fs = init_data(main)
            update_fs1 = main.getEnkfFsManager().getFileSystem("target1")

            # The first smoother update without row scaling
            es_update = ESUpdate(main)
            run_context = ErtRunContext.ensemble_smoother_update(init_fs, update_fs1)
            rng = main.rng()
            es_update.smootherUpdate(run_context)

            # Configure the local updates
            local_config = main.getLocalConfig()
            local_config.clear()
            obs = local_config.createObsdata("OBSSET_LOCAL")
            obs.addNode("WBHP0")

            ministep1 = local_config.createMinistep("MINISTEP1")
            local_data1 = local_config.createDataset("LOCAL1")
            local_data1.addNode("PORO")
            row_scaling1 = local_data1.row_scaling("PORO")
            ministep1.attachDataset(local_data1)
            ministep1.attachObsset(obs)

            ministep2 = local_config.createMinistep("MINISTEP2")
            local_data2 = local_config.createDataset("LOCAL2")
            local_data2.addNode("PORO")
            row_scaling2 = local_data2.row_scaling("PORO")
            ministep2.attachDataset(local_data2)
            ministep2.attachObsset(obs)

            updatestep = local_config.getUpdatestep()
            updatestep.attachMinistep(ministep1)
            updatestep.attachMinistep(ministep2)

            # Apply the row scaling
            ens_config = main.ensembleConfig()
            poro_config = ens_config["PORO"]
            field_config = poro_config.getFieldModelConfig()
            grid = main.eclConfig().getGrid()

            row_scaling1.assign(field_config.get_data_size(), SelectLayer(0, grid))
            row_scaling2.assign(field_config.get_data_size(), SelectLayer(1, grid))

            update_fs2 = main.getEnkfFsManager().getFileSystem("target2")
            es_update = ESUpdate(main)
            run_context = ErtRunContext.ensemble_smoother_update(init_fs, update_fs2)
            es_update.smootherUpdate(run_context)

            init_node = EnkfNode(poro_config)
            node1 = EnkfNode(poro_config)
            node2 = EnkfNode(poro_config)
            for iens in range(main.getEnsembleSize()):
                node_id = NodeId(0, iens)

                init_node.load(init_fs, node_id)
                node1.load(update_fs1, node_id)
                node2.load(update_fs2, node_id)

                init_field = init_node.asField()
                field1 = node1.asField()
                field2 = node2.asField()
                for iv, v1, v2 in zip(init_field, field1, field2):
                    assert iv != v1
    def test_reuse_ALL_ACTIVE(self):
        random_seed = "ABCDEFGHIJK0123456"
        with ErtTestContext("row_scaling", self.config_file) as tc:
            main = tc.getErt()
            grid = main.eclConfig().getGrid()
            init_fs = init_data(main)
            es_update = ESUpdate(main)
            update_fs1 = main.getEnkfFsManager().getFileSystem("target1")
            run_context = ErtRunContext.ensemble_smoother_update(init_fs, update_fs1)
            rng = main.rng()
            rng.setState(random_seed)
            # Normal update without any local configuration
            es_update.smootherUpdate(run_context)

            local_config = main.getLocalConfig()
            local_config.clear_active()
            with self.assertRaises(KeyError):
                obs_data = local_config.copyObsdata("NO_SUCH_OBS", "my_obs")

            local_data = local_config.createDataset("LOCAL")
            local_data.addNode("PORO")
            obs_data = local_config.copyObsdata("ALL_OBS", "my_obs")
            ministep = local_config.createMinistep("MINISTEP_LOCAL")
            ministep.attachDataset(local_data)
            ministep.attachObsset(obs_data)
            updatestep = local_config.getUpdatestep()
            updatestep.attachMinistep(ministep)

            update_fs2 = main.getEnkfFsManager().getFileSystem("target2")
            run_context = ErtRunContext.ensemble_smoother_update(init_fs, update_fs2)
            rng.setState(random_seed)
            # Local update with reused ALL_OBS observation configuration
            es_update.smootherUpdate(run_context)

            del obs_data["WBHP0"]
            ministep2 = local_config.createMinistep("MINISTEP_LOCAL2")
            obs_data2 = local_config.createObsdata("OBSDATA2")
            obs_data2.addNode("WBHP0")
            ministep2.attachDataset(local_data)
            ministep2.attachObsset(obs_data2)
            updatestep.attachMinistep(ministep2)
            update_fs3 = main.getEnkfFsManager().getFileSystem("target3")
            run_context = ErtRunContext.ensemble_smoother_update(init_fs, update_fs3)
            # Local update with two ministeps - where one observation has been removed from the first
            es_update.smootherUpdate(run_context)

            ens_config = main.ensembleConfig()
            poro_config = ens_config["PORO"]
            update_node1 = EnkfNode(poro_config)
            update_node2 = EnkfNode(poro_config)
            update_node3 = EnkfNode(poro_config)
            for iens in range(main.getEnsembleSize()):
                node_id = NodeId(0, iens)

                update_node1.load(update_fs1, node_id)
                update_node2.load(update_fs2, node_id)
                update_node3.load(update_fs3, node_id)

                field1 = update_node1.asField()
                field2 = update_node2.asField()
                field3 = update_node3.asField()

                for k in range(grid.nz):
                    for j in range(grid.ny):
                        for i in range(grid.nx):
                            assert field1.ijk_get_double(
                                i, j, k
                            ) == field2.ijk_get_double(i, j, k)

                            f1 = field1.ijk_get_double(i, j, k)
                            f3 = field3.ijk_get_double(i, j, k)

                            # Due to the randomness in the sampling process,
                            # which becomes different when the update steps is
                            # split in two ministeps we can not enforce
                            # equality here.

                            diff = abs(f1 - f3)
                            assert diff < 0.01
    def test_row_scaling_using_assign_vector(self):
        random_seed = "ABCDEFGHIJK0123456"
        with ErtTestContext("row_scaling", self.config_file) as tc:
            main = tc.getErt()
            init_fs = init_data(main)
            update_fs1 = main.getEnkfFsManager().getFileSystem("target1")

            # The first smoother update without row scaling
            es_update = ESUpdate(main)
            run_context = ErtRunContext.ensemble_smoother_update(init_fs, update_fs1)
            rng = main.rng()
            rng.setState(random_seed)
            es_update.smootherUpdate(run_context)

            # Configure the local updates
            local_config = main.getLocalConfig()
            local_config.clear()
            local_data = local_config.createDataset("LOCAL")
            local_data.addNode("PORO")
            obs = local_config.createObsdata("OBSSET_LOCAL")
            obs.addNode("WWCT0")
            obs.addNode("WBHP0")
            ministep = local_config.createMinistep("MINISTEP_LOCAL")
            ministep.attachDataset(local_data)
            ministep.attachObsset(obs)
            updatestep = local_config.getUpdatestep()
            updatestep.attachMinistep(ministep)

            # Apply the row scaling
            row_scaling = local_data.row_scaling("PORO")
            ens_config = main.ensembleConfig()
            poro_config = ens_config["PORO"]
            field_config = poro_config.getFieldModelConfig()
            grid = main.eclConfig().getGrid()

            scaling = ScalingTest(grid)
            scaling_vector = np.ndarray(
                [field_config.get_data_size()], dtype=np.float32
            )
            for i in range(field_config.get_data_size()):
                scaling_vector[i] = scaling(i)
            row_scaling.assign_vector(scaling_vector)

            # Second update with row scaling
            update_fs2 = main.getEnkfFsManager().getFileSystem("target2")
            es_update = ESUpdate(main)
            run_context = ErtRunContext.ensemble_smoother_update(init_fs, update_fs2)
            rng.setState(random_seed)
            es_update.smootherUpdate(run_context)

            # Fetch the three values initial, update without row scaling and
            # update with row scaling and verify that the row scaling has been
            # correctly applied.
            init_node = EnkfNode(poro_config)
            update_node1 = EnkfNode(poro_config)
            update_node2 = EnkfNode(poro_config)
            for iens in range(main.getEnsembleSize()):
                node_id = NodeId(0, iens)

                init_node.load(init_fs, node_id)
                update_node1.load(update_fs1, node_id)
                update_node2.load(update_fs2, node_id)

                assert_field_update(
                    grid,
                    init_node.asField(),
                    update_node1.asField(),
                    update_node2.asField(),
                )