Beispiel #1
0
    def __init__(self,
                 solver,
                 res_match_obj,
                 normalize_d_to_u=True,
                 model_window=IdentityModelWindow(),
                 data_window=IdentityDataWindow(),
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1):

        self.solver = solver

        self.modeling_tools = TemporalModeling(solver)

        self.parallel_wrap_shot = parallel_wrap_shot

        self.W_model = model_window
        self.W_data = data_window

        TemporalLeastSquares.__init__(self, solver, parallel_wrap_shot,
                                      imaging_period)
        self.res_match_obj = res_match_obj  #The residual match object that is used for normalizing the data.
        self.normalize_d_to_u = normalize_d_to_u

        if res_match_obj._synToFld:
            raise Exception(
                "I'm assuming synToFld should be false. It determines the order of synthetic and true data in the call self.res_match_obj.match in the self._residual function. The covmatch option of the match routine will in this case pass fld as first argument and syn as second. The udmatch array contains the scaling factor for the first argument in self.res_match_obj.match to the second this way"
            )
Beispiel #2
0
    def __init__(self,
                 solver,
                 ot_param=None,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1,
                 normalize_trace=False):
        """imaging_period: Imaging happens every 'imaging_period' timesteps. Use higher numbers to reduce memory consumption at the cost of lower gradient accuracy.
            By assigning this value to the class, it will automatically be used when the gradient function of the temporal objective function is called in an inversion context.
        """
        self.solver = solver
        self.modeling_tools = TemporalModeling(solver)
        self.parallel_wrap_shot = parallel_wrap_shot
        self.imaging_period = int(imaging_period)  # Needs to be an integer
        self.normalize_trace = normalize_trace
        self.trans_func = 'id'
        self.trans_factor = 1.0
        self.filter_op = False
        self.noise_factor = None

        if ot_param is not None:
            self.trans_func = ot_param['trans_func_type']
            self.trans_factor = ot_param['trans_func_factor']
            self.velocity_bound = ot_param['velocity_bound']
            self.filter_op = ot_param['filter_op']
            self.freq_band = ot_param['freq_band']
            self.noise_factor = ot_param['noise_factor']
    def __init__(self,
                 solver,
                 filter_op=None,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 transform_mode='linear',
                 imaging_period=1,
                 c_ratio=5.0,
                 exp_a=1.0,
                 env_p=2.0,
                 auto_expa=True,
                 paddata=False,
                 FlagCnsdNeg=False):
        """imaging_period: Imaging happens every 'imaging_period' timesteps. Use higher numbers to reduce memory consumption at the cost of lower gradient accuracy.
            By assigning this value to the class, it will automatically be used when the gradient function of the temporal objective function is called in an inversion context.
        """
        self.solver = solver
        self.modeling_tools = TemporalModeling(solver)

        self.parallel_wrap_shot = parallel_wrap_shot
        self.transform_mode = transform_mode

        self.imaging_period = int(imaging_period)  #Needs to be an integer
        self.filter_op = filter_op
        self.c_ratio = c_ratio
        self.exp_a = exp_a
        self.env_p = env_p
        self.paddata = paddata
        self.auto_expa = auto_expa
        self.FlagCnsdNeg = FlagCnsdNeg
Beispiel #4
0
    def __init__(self,
                 solver,
                 h,
                 filter_op=None,
                 dm_extend=None,
                 max_sub_offset=0.0,
                 weight_matrix=None,
                 regularization_value=None,
                 krylov_maxiter=10,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1):
        """imaging_period: Imaging happens every 'imaging_period' timesteps. Use higher numbers to reduce memory consumption at the cost of lower gradient accuracy.
            By assigning this value to the class, it will automatically be used when the gradient function of the temporal objective function is called in an inversion context.
        """
        self.solver = solver
        self.modeling_tools = TemporalModeling(solver)

        self.parallel_wrap_shot = parallel_wrap_shot

        self.imaging_period = int(imaging_period)  # Needs to be an integer
        self.filter_op = filter_op

        self.weight_matrix = weight_matrix
        self.regularization_value = regularization_value
        self.krylov_maxiter = krylov_maxiter

        self.max_sub_offset = max_sub_offset
        self.h = h
        self.dm_extend = dm_extend
Beispiel #5
0
    def __init__(self,
                 solver,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 modeling_kwargs={}):
        self.solver = solver
        self.modeling_tools = HybridModeling(solver, **modeling_kwargs)

        self.parallel_wrap_shot = parallel_wrap_shot
Beispiel #6
0
 def __init__(self,
              tomo_obj,
              data_obs,
              sigma,
              parallel_wrap_shot=ParallelWrapShotNull(),
              cnn=None):
     self.data_obs = data_obs
     self.tomo_obj = tomo_obj
     self.sigma = sigma
     self.cnn = cnn
    def __init__(self,
                 solver,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1):
        """imaging_period: Imaging happens every 'imaging_period' timesteps. Use higher numbers to reduce memory consumption at the cost of lower gradient accuracy.
            By assigning this value to the class, it will automatically be used when the gradient function of the temporal objective function is called in an inversion context.
        """
        self.solver = solver
        self.modeling_tools = TemporalModeling(solver)

        self.parallel_wrap_shot = parallel_wrap_shot

        self.imaging_period = int(imaging_period)  #Needs to be an integer
Beispiel #8
0
    def __init__(self,
                 solver,
                 shots_d1,
                 shots_d0,
                 res_match_obj,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1,
                 norm_both_to_d0=False,
                 normalize_d_to_u=False):
        """imaging_period: Imaging happens every 'imaging_period' timesteps. Use higher numbers to reduce memory consumption at the cost of lower gradient accuracy.
            By assigning this value to the class, it will automatically be used when the gradient function of the temporal objective function is called in an inversion context.
        """

        TemporalLeastSquares.__init__(self, solver, parallel_wrap_shot,
                                      imaging_period)
        self.res_match_obj = res_match_obj  #The residual match object that is used for normalizing the data.

        self.shots_u0_set = False  #When this is set, the next two items will be generated. See _generate_data_on_shots_u0
        self.fixed_dt_synthetic = None
        self.fixed_ts = None
        self.shots_u0 = None

        self.shots_d0 = shots_d0
        self.shots_d1 = shots_d1
        self.norm_both_to_d0 = norm_both_to_d0  #POORLY CHOSEN VARIABLE NAME NOW THAT I ALSO ALLOW D TO BE NORMALIZED TO U. THIS VARIABLE SHOULD MEAN NORMALIZE BOTH TO 0

        self.shots_dict = dict(
        )  #in _residual we will index this to find out which d0 and u0 shot we should use when forming the double difference.
        #d0 and d1 may have slightly different positions. I just need their order to be the same

        self.normalize_d_to_u = normalize_d_to_u  #When I initiall wrote this code I assumed we would always normalize u to d. I just made this modification to see if d to u makes any difference.

        for shot in shots_d1:
            i = shots_d1.index(shot)
            pos = shot.sources.position
            self.shots_dict[pos] = i

        #I am not normalizing the baseline synthetic here, because I am planning to do the same as in NormalizedAmplitudeTemporalLeastSquares.
        #There I interpolate the true data to solver.ts(). This can change if the max velocity changes over the iterations

        #To reduce the probability of errors when matching d1 and d0 shots I am going to assume that all shots have increasing x positions.
        #Here I will just verify this
        self._verify_shots_x_position_increasing(shots_d1)
        self._verify_shots_x_position_increasing(shots_d0)

        if res_match_obj._synToFld:
            raise Exception(
                "I'm assuming synToFld should be false. It determines the order of synthetic and true data in the call self.res_match_obj.match in the self._residual function. The covmatch option of the match routine will in this case pass fld as first argument and syn as second. The udmatch array contains the scaling factor for the first argument in self.res_match_obj.match to the second this way"
            )
Beispiel #9
0
    def __init__(self,
                 solver,
                 model_window=IdentityModelWindow(),
                 data_window=IdentityDataWindow(),
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1):

        self.solver = solver

        self.modeling_tools = TemporalModeling(solver)

        self.parallel_wrap_shot = parallel_wrap_shot

        self.W_model = model_window
        self.W_data = data_window
        self.imaging_period = imaging_period
Beispiel #10
0
    def __init__(self, solver=None, parallel_wrap_shot=ParallelWrapShotNull()):
        """Construct the simple objective class
            We construct the following objective function:

            f(x) = exp(-0.5 * |x|^2)

            The corresponding gradient is

            g(x) = - exp(-0.5 * |x|^2) * x

            ____________________________________________________________________

            In this class, the input solver and parallel_wrap_shot are not
            necessary. The reason that we keep them is that we want to make this
            class consistant with the objective class of pysit. So that, they can
            be called in the same way in the Gradient Test. 

        """

        self.parallel_wrap_shot = parallel_wrap_shot
        self.solver = solver
Beispiel #11
0
    def __init__(self,
                 solver,
                 filter_op=None,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1,
                 normalize_trace=False,
                 regularization=None,
                 normalize_obs=True,
                 DownSample_op=opI()):
        """imaging_period: Imaging happens every 'imaging_period' timesteps. Use higher numbers to reduce memory consumption at the cost of lower gradient accuracy.
            By assigning this value to the class, it will automatically be used when the gradient function of the temporal objective function is called in an inversion context.
        """
        self.solver = solver
        self.modeling_tools = TemporalModeling(solver)
        self.regularization = regularization

        self.parallel_wrap_shot = parallel_wrap_shot

        self.imaging_period = int(imaging_period)  # Needs to be an integer
        self.filter_op = filter_op
        self.normalize_trace = normalize_trace
        self.normalize_obs = normalize_obs
        self.DownSample_op = DownSample_op
    def __init__(self,
                 solver,
                 shots_d1,
                 shots_d0,
                 res_match_obj,
                 parallel_wrap_shot=ParallelWrapShotNull(),
                 imaging_period=1):

        TemporalLeastSquares.__init__(self, solver, parallel_wrap_shot,
                                      imaging_period)
        self.res_match_obj = res_match_obj  #The residual match object that is used for normalizing the data.

        self.shots_u0_set = False  #When this is set, the next two items will be generated. See _generate_data_on_shots_u0
        self.fixed_dt_synthetic = None
        self.fixed_ts = None
        self.shots_u0 = None

        self.shots_d0 = shots_d0
        self.shots_d1 = shots_d1
        self.shots_dict = dict(
        )  #in _residual we will index this to find out which d0 and u0 shot we should use when forming the double difference.
        #d0 and d1 may have slightly different positions. I just need their order to be the same

        for shot in shots_d1:
            i = shots_d1.index(shot)
            pos = shot.sources.position
            self.shots_dict[pos] = i

        #To reduce the probability of errors when matching d1 and d0 shots I am going to assume that all shots have increasing x positions.
        #Here I will just verify this
        self._verify_shots_x_position_increasing(shots_d1)
        self._verify_shots_x_position_increasing(shots_d0)

        if res_match_obj._synToFld:
            raise Exception(
                "I'm assuming synToFld should be false. It determines the order of synthetic and true data in the call self.res_match_obj.match in the self._residual function. The covmatch option of the match routine will in this case pass fld as first argument and syn as second. The udmatch array contains the scaling factor for the first argument in self.res_match_obj.match to the second this way"
            )
Beispiel #13
0
def equispaced_acquisition(mesh, wavelet,
                           sources=1,
                           receivers='max',
                           source_depth=None,
                           source_kwargs={},
                           receiver_depth=None,
                           receiver_kwargs={},
                           parallel_shot_wrap=ParallelWrapShotNull()
                           ):

    m = mesh
    d = mesh.domain

    xmin = d.x.lbound
    xmax = d.x.rbound

    zmin = d.z.lbound
    zmax = d.z.rbound

    if m.dim == 3:
        ymin = d.y.lbound
        ymax = d.y.rbound


    if source_depth is None:
        source_depth = zmin

    if receiver_depth is None:
        receiver_depth = zmin

    shots = list()

    max_sources = m.x.n

    if m.dim == 2:
        if receivers == 'max':
            receivers = m.x.n
        if sources == 'max':
            sources = m.x.n

        if receivers > m.x.n:
            raise ValueError('Number of receivers exceeds mesh nodes.')
        if sources > m.x.n:
            raise ValueError('Number of sources exceeds mesh nodes.')

        xpos = np.linspace(xmin, xmax, receivers)
        receiversbase = ReceiverSet(m, [PointReceiver(m, (x, receiver_depth), **receiver_kwargs) for x in xpos])

        local_sources = sources // parallel_shot_wrap.size, 1

    if m.dim == 3:

        if receivers == 'max':
            receivers = (m.x.n, m.y.n) # x, y
        if sources == 'max':
            sources = (m.x.n, m.y.n) # x, y

        if receivers[0] > m.x.n or receivers[1] > m.y.n:
            raise ValueError('Number of receivers exceeds mesh nodes.')
        if sources[0] > m.x.n or sources[1] > m.y.n:
            raise ValueError('Number of sources exceeds mesh nodes.')

        xpos = np.linspace(xmin, xmax, receivers[0])
        ypos = np.linspace(ymin, ymax, receivers[1])
        receiversbase = ReceiverSet(m, [PointReceiver(m, (x, y, receiver_depth), **receiver_kwargs) for x in xpos for y in ypos])

        local_sources = sources[0] // parallel_shot_wrap.size, sources[1] // parallel_shot_wrap.size

    for i in range(int(local_sources[0])):
        for j in range(int(local_sources[1])):

            idx = i + local_sources[0]*parallel_shot_wrap.rank
            jdx = j + local_sources[1]*parallel_shot_wrap.rank

            if m.dim == 2:
                srcpos = (xmin + (xmax-xmin)*(idx+1.0)/(sources+1.0), source_depth)
            elif m.dim == 3:
                srcpos = (xmin + (xmax-xmin)*(idx+1.0)/(sources[0]+1.0), ymin + (ymax-ymin)*(jdx+1.0)/(sources[1]+1.0), source_depth)

            # Define source location and type
            source = PointSource(m, srcpos, wavelet, **source_kwargs)

            # Define set of receivers
            receivers = copy.deepcopy(receiversbase)

            # Create and store the shot
            shot = Shot(source, receivers)
            shots.append(shot)

    return shots
def equispaced_acquisition_given_data(data, mesh, wavelet,
                                      odata, ddata, ndata,
                                      source_kwargs={},
                                      receiver_kwargs={},
                                      parallel_shot_wrap=ParallelWrapShotNull()
                                      ):


    source_depth=None,
    receiver_depth=None,

    m = mesh
    d = mesh.domain

    xmin = d.x.lbound
    xmax = d.x.rbound

    zmin = d.z.lbound
    zmax = d.z.rbound

    if m.dim == 2:
        data_time, data_xrec, data_zrec, data_xsrc, data_zsrc = odn2grid_data_2D_time(odata, ddata, ndata)

    if m.dim == 3:
        data_time, data_xrec, data_yrec, data_zrec, data_xsrc, data_ysrc, data_zsrc = odn2grid_data_3D_time(odata, ddata, ndata)

    if m.dim == 3:
        ymin = d.y.lbound
        ymax = d.y.rbound

    source_depth = data_zsrc[0]
    receiver_depth = data_zrec[0] 

    shots = list()

    max_sources = m.x.n

    if m.dim == 2:
        receivers = ndata[1]
        sources = ndata[3]

        xpos_rec = data_xrec
        
        receiversbase = ReceiverSet(m, [PointReceiver(m, (x, receiver_depth), **receiver_kwargs) for x in xpos_rec])

        
        if np.mod(sources, parallel_shot_wrap.size) != 0:
            raise ValueError('Currently, we only support the case that mod(number of sources, number of processes) = 0')
        local_sources = sources / parallel_shot_wrap.size

    if m.dim == 3:

        receivers = (ndata[1], ndata[2])
        sources = (ndata[4], ndata[5])
        
        xpos_rec = data_xrec
        ypos_rec = data_yrec
        receiversbase = ReceiverSet(m, [PointReceiver(m, (x, y, receiver_depth), **receiver_kwargs) for x in xpos_rec for y in ypos_rec])

        if np.mod(np.prod(sources), parallel_shot_wrap.size) != 0:
            raise('Currently, we only support the case that mod(number of sources, number of processes) = 0')
        local_sources = np.prod(sources) / parallel_shot_wrap.size

    print(type(local_sources))
    local_sources = int(local_sources)

    if m.dim == 2:
        if parallel_shot_wrap.rank == 0:
            data_local = data[:,:,:,0:local_sources,:].squeeze()

            for i in range(1, parallel_shot_wrap.size):
                data_send = data[:,:,:,i*local_sources:(i+1)*local_sources,:]
                parallel_shot_wrap.comm.send(data_send, dest=i, tag=i)

        else:
            data_receive=parallel_shot_wrap.comm.recv(source=0, tag=parallel_shot_wrap.rank)
            print('Receive data from process ', 0)

            data_local = data_receive.squeeze()

    if m.dim == 3:
        if parallel_shot_wrap.rank == 0:
            data_local = get_local_data(data, n, local_sources, 0)
            for k in range(1, parallel_shot_wrap.size):
                data_send = get_local_data(data, n, local_source, k)
                parallel_shot_wrap.comm.send(data_send, dest=k, tag=k)

        else:
            data_local=parallel_shot_wrap.comm.recv(source=0, tag=parallel_shot_wrap.rank)
            print('Receive data from process ', 0)
            # data_local = np.zeros((data_time, data_xrec*data_yrec, local_sources))
            # for k in range(local_sources):


    for k in range(int(local_sources)):
        index_true = int(local_sources) * parallel_shot_wrap.rank + k
        subindex = np.unravel_index(index_true, sources)

        if m.dim == 2:
            idx = subindex
        
        if m.dim == 3:
            idx = subindex[0]
            jdx = subindex[1]

        if m.dim == 2:
            srcpos = (data_xsrc[idx], source_depth)
        elif m.dim == 3:
            srcpos = (data_xsrc[idx], data_ysrc[jdx], source_depth)

        # Define source location and type
        source = PointSource(m, srcpos, wavelet, **source_kwargs)

        # Define set of receivers
        receivers = copy.deepcopy(receiversbase)

        receivers.data = data_local[:,:,k]

        # Create and store the shot
        shot = Shot(source, receivers)
        shots.append(shot)


    return shots
Beispiel #15
0
    def __call__(self,
                 shots,
                 initial_model,
                 n_cnn_para,
                 nsmps,
                 beta,
                 noise_sigma=1.0,
                 isuq=False,
                 print_interval=10,
                 save_interval=None,
                 initial_value_cnn=None,
                 parallel_wrap=ParallelWrapShotNull(),
                 verbose=False,
                 append=False,
                 write=False,
                 **kwargs):
        """The main function for executing a number of steps of the descent
        algorith.

        Most things can be done without directly overriding this function.

        Parameters
        ----------
        shots : list of pysit.Shot
            List of Shots for which to compute on.
        initial_value : solver.WaveParameters
            Initial guess for the iteration.
        iteration_parameters : int, iterable
            Loop iteration parameters, like number of steps or frequency sets.
        <blank>_frequency : int, optional kwarg
            Frequency with which to store histories.  Detailed in reset method.
        verbose : bool
            Verbosity flag.
        linesearch_configuration : dictionary
            Possible parameters for linesearch, for more details, please check the introduction of the function set_linesearch_configuration

        """
        if initial_value_cnn is None:
            m0_cnn = tf.random.uniform([1, n_cnn_para])
        else:
            m0_cnn = initial_value_cnn

        phi0 = self.objective_function.evaluate(shots, initial_model, m0_cnn) / noise_sigma**2.0
        Ms = []
        A_accept = []
        Phi = []
        Beta = []
        Ms.append(m0_cnn)
        if parallel_wrap.use_parallel:
            if parallel_wrap.comm.Get_rank() == 0:
                r_probs = np.random.uniform(0.0, 1.0, nsmps)
            else:
                r_probs = None

            r_probs = parallel_wrap.comm.bcast(r_probs, root=0) 
                
        else:
            r_probs = np.random.uniform(0.0, 1.0, nsmps)

        m_min_cnn = m0_cnn
        phi_min = phi0
        

        for i in range(nsmps):
            # mtmp_cnn = tf.random.uniform([1, n_cnn_para])
            Beta.append(beta)
            if parallel_wrap.use_parallel:
                if parallel_wrap.comm.Get_rank() == 0:
                    mtmp_cnn = tf.random.normal([1, n_cnn_para])
                else:
                    mtmp_cnn = None

                mtmp_cnn = parallel_wrap.comm.bcast(mtmp_cnn, root=0) 
                
            else:
                mtmp_cnn = tf.random.normal([1, n_cnn_para])

            m1_cnn = np.sqrt(1-beta**2.0)*m0_cnn + beta*mtmp_cnn
            phi1 = self.objective_function.evaluate(shots, initial_model, m1_cnn) / noise_sigma**2.0

            if phi1 < phi_min:
                phi_min = phi1
                m_min_cnn = m1_cnn

            a_accept = np.min((np.exp(phi0-phi1), 1))
            A_accept.append(a_accept)
            Phi.append(phi1)
            # print('Accept probability:', a_accept)
            
            if np.mod(i,print_interval) == 0:
                if self.use_parallel is True:
                    if self.objective_function.parallel_wrap_shot.comm.Get_rank() == 0:
                        print('Iteration:', i)
                        print('f: ', phi_min)
                else:
                    print('Iteration:', i)
                    print('f: ', phi_min)

            if a_accept > r_probs[i]:
                Ms.append(m1_cnn)
                m0_cnn = m1_cnn
                phi0 = phi1
                if a_accept > 0.8:
                    beta *= 1.2
            else:
                Ms.append(m0_cnn)
                if a_accept < 0.1:
                    if beta > 1e-4:
                        beta *= 0.5

            if save_interval is not None:
                if np.mod(i,save_interval) == 0:
                    if (parallel_wrap.use_parallel is None) or (parallel_wrap.comm.Get_rank() == 0):
                        if i == 0:
                            Snp = np.array(Ms)
                        else:
                            Msi = Ms[len(Snp):len(Ms)]
                            Snpi = np.array(Msi)
                            nsize = np.shape(Snpi)
                            Snpi = np.reshape(Snpi, [nsize[0], nsize[-1]])
                            print(np.shape(Snp))
                            print(np.shape(Snpi))
                            Snp = np.concatenate((Snp, Snpi), axis=0)
                        
                        n_size = np.shape(Snp)
                        n_size_new = [n_size[0], n_size[-1]]
                        Snp = np.reshape(Snp, n_size_new)
                        write_data('./Samples.mat', Snp, [1,1], [1,1], n_size_new)
                        write_data('./MAP.mat', np.array(m_min_cnn), [1,1], [1,1], np.array(m_min_cnn).shape)
                        write_data('./probability.mat', A_accept, [1], [1], len(A_accept))
                        write_data('./objective_function.mat', Phi, [1], [1], len(Phi))
                        write_data('./betas.mat', Beta, [1], [1], len(Beta))

                    if parallel_wrap.use_parallel is not None:
                        parallel_wrap.comm.Barrier()


            

        result = dict()
        result['MAP'] = m_min_cnn
        result['samples'] = Ms
        result['accept_prob'] = A_accept
        result['Phi'] = Phi

        return result
    def __init__(self, solver, parallel_wrap_shot=ParallelWrapShotNull()):
        self.solver = solver
        self.modeling_tools = FrequencyModeling(solver)

        self.parallel_wrap_shot = parallel_wrap_shot
Beispiel #17
0
    def __init__(self, solver, parallel_wrap_shot=ParallelWrapShotNull()):
        self.solver = solver
        self.modeling_tools = None

        self.parallel_wrap_shot = parallel_wrap_shot
def marine_acquisition(mesh, wavelet, sources_x_locations=None,
                       sources_y_locations=None,
                       max_offset_x=None,
                       max_offset_y=None,
                       receivers_dx=None,
                       receivers_dy=None,
                       source_depth=None,
                       source_kwargs={},
                       receiver_depth=None,
                       receiver_kwargs={},
                       parallel_shot_wrap=ParallelWrapShotNull()):

    if sources_x_locations is None:
        raise ValueError(
            "The horizontal locations of sources are not defined, please set values to variable 'sources_x_locations' ")

    if max_offset_x is None:
        raise ValueError(
            "The horizontal maximal offset is not defined, please set values to variable 'max_offset_x' ")

    if receivers_dx is None:
        raise ValueError(
            "The horizontal receiver sampling interval is not defined, please set values to variable 'receivers_dx' ")

    m = mesh
    d = mesh.domain

    xmin = d.x.lbound
    xmax = d.x.rbound

    zmin = d.z.lbound
    zmax = d.z.rbound

    if m.dim == 3:
        raise ValueError(
            "3D Marine tow string acquisition has not been implemented")

    if source_depth is None:
        source_depth = zmin

    if receiver_depth is None:
        receiver_depth = zmin

    shots = list()

    max_sources = len(sources_x_locations)

    if m.dim == 2:
        sources = len(sources_x_locations)
        local_sources = sources / parallel_shot_wrap.size

    for k in range(int(local_sources)):
        index_true = int(local_sources) * parallel_shot_wrap.rank + k
        subindex = np.unravel_index(index_true, sources)
        idx = subindex[0]

        if m.dim == 3:
            ## 3D marine acquisition has not been implemented
            jdx = subindex[1]

        if m.dim == 2:
            # srcpos = (xmin + (xmax-xmin)*(idx+1.0)/(sources+1.0), source_depth)
            srcpos = (sources_x_locations[idx], source_depth)
        elif m.dim == 3:
            # srcpos = (xmin + (xmax-xmin)*(idx+1.0)/(sources[0]+1.0), ymin + (
            #     ymax-ymin)*(jdx+1.0)/(sources[1]+1.0), source_depth)
            srcpos = (sources_x_locations[idx], sources_y_locations[jdx])

        # Define source location and type
        source = PointSource(m, srcpos, wavelet, **source_kwargs)

        # Define set of receivers

        xpos = np.arange(
            sources_x_locations[idx], max_offset_x+sources_x_locations[idx], receivers_dx)
        receiversbase = ReceiverSet(
            m, [PointReceiver(m, (x, receiver_depth), **receiver_kwargs) for x in xpos])

        receivers = copy.deepcopy(receiversbase)

        # Create and store the shot
        shot = Shot(source, receivers)
        shots.append(shot)

    return shots
def equispaced_acquisition_given_locations(mesh, wavelet,
                                           sources_x_locations=None,
                                           sources_y_locations=None,
                                           receivers_x_locations=None,
                                           receivers_y_locations=None,
                                           source_depth=None,
                                           source_kwargs={},
                                           receiver_depth=None,
                                           receiver_kwargs={},
                                           parallel_shot_wrap=ParallelWrapShotNull()
                                          ):

    ## Define the acquisition geometry for given sources locations and receivers locations

    if sources_x_locations is None:
        raise ValueError("The horizontal locations of sources are not defined, please set values to variable 'sources_x_locations' ")

    if receivers_x_locations is None:
        raise ValueError("The horizontal locations of receivers are not defined, please set values to variable 'receivers_x_locations' ")

    m = mesh
    d = mesh.domain

    xmin = d.x.lbound
    xmax = d.x.rbound

    zmin = d.z.lbound
    zmax = d.z.rbound

    if m.dim == 3:
        ymin = d.y.lbound
        ymax = d.y.rbound

    if source_depth is None:
        source_depth = zmin

    if receiver_depth is None:
        receiver_depth = zmin

    shots = list()

    max_sources = len(sources_x_locations)

    if m.dim == 2:
        receivers = len(receivers_x_locations)
        sources = len(sources_x_locations)

        xpos = receivers_x_locations
        receiversbase = ReceiverSet(m, [PointReceiver(m, (x, receiver_depth), **receiver_kwargs) for x in xpos])

        local_sources = sources / parallel_shot_wrap.size

    if m.dim == 3:

        receivers = (len(receivers_x_locations), len(receivers_y_locations))  # x, y
        
        sources = (len(sources_x_locations), len(sources_y_locations))  # x, y

        if receivers[0] > m.x.n or receivers[1] > m.y.n:
            raise ValueError('Number of receivers exceeds mesh nodes.')
        if sources[0] > m.x.n or sources[1] > m.y.n:
            raise ValueError('Number of sources exceeds mesh nodes.')

        xpos = receivers_x_locations
        ypos = receivers_y_locations
        receiversbase = ReceiverSet(m, [PointReceiver(
            m, (x, y, receiver_depth), **receiver_kwargs) for x in xpos for y in ypos])

        local_sources = np.prod(sources) / parallel_shot_wrap.size

    print(type(local_sources))
    print(local_sources)

    for k in range(int(local_sources)):
        index_true = int(local_sources) * parallel_shot_wrap.rank + k
        subindex = np.unravel_index(index_true, sources)
        idx = subindex[0]

        if m.dim == 3:
            jdx = subindex[1]

        if m.dim == 2:
            # srcpos = (xmin + (xmax-xmin)*(idx+1.0)/(sources+1.0), source_depth)
            srcpos = (sources_x_locations[idx], source_depth)
        elif m.dim == 3:
            # srcpos = (xmin + (xmax-xmin)*(idx+1.0)/(sources[0]+1.0), ymin + (
            #     ymax-ymin)*(jdx+1.0)/(sources[1]+1.0), source_depth)
            srcpos = (sources_x_locations[idx], sources_y_locations[jdx])

        # Define source location and type
        source = PointSource(m, srcpos, wavelet, **source_kwargs)

        # Define set of receivers
        receivers = copy.deepcopy(receiversbase)

        # Create and store the shot
        shot = Shot(source, receivers)
        shots.append(shot)

    return shots