text:
#ifndef _EM_LA_H_
#define _EM_LA_H_ 1

#include <petsc.h>

struct EMContext;

PetscErrorCode access_vec(Vec, std::vector<PetscInt> &, int, double *);

PetscErrorCode setup_ams(EMContext *);
PetscErrorCode destroy_ams(EMContext *);

PetscErrorCode create_pc(EMContext *);
PetscErrorCode destroy_pc(EMContext *);
PetscErrorCode pc_apply_b(PC, Vec, Vec);

PetscErrorCode matshell_createvecs_a(Mat, Vec *, Vec *);
PetscErrorCode matshell_mult_a(Mat, Vec, Vec);

PetscErrorCode solve_linear_system(EMContext *, const PETScBlockVector &, PETScBlockVector &, PetscInt, PetscReal);

#endif

max_stars_repo_name: emfem/emfem

max_issues_repo_name: emfem/emfem

max_forks_repo_name: emfem/emfem


text:
//
// Copyright (c) 2009, Markus Rickert
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

#include <chrono>
#include <memory>
#include <nlopt.h>
#include <random>
#include <utility>

#include "Exception.h"
#include "IterativeInverseKinematics.h"

namespace rl
{
	namespace mdl
	{
		class RL_MDL_EXPORT WeightedInverseKinematics : public IterativeInverseKinematics
		{
		public:
			class Exception : public ::rl::mdl::Exception
			{
			public:
				Exception(const ::nlopt_result& result);

				virtual ~Exception() throw();

				static void check(const ::nlopt_result& result);

				::nlopt_result getResult() const;

				virtual const char* what() const throw();

			protected:

			private:
				::nlopt_result result;
			};

			WeightedInverseKinematics(Kinematic* kinematic);

			virtual ~WeightedInverseKinematics();

			::rl::math::Real getFunctionToleranceAbsolute() const;

			::rl::math::Real getFunctionToleranceRelative() const;

			const ::rl::math::Vector& getLowerBound() const;

			::rl::math::Vector getOptimizationToleranceAbsolute() const;

			::rl::math::Real getOptimizationToleranceRelative() const;

			const ::rl::math::Vector& getUpperBound() const;

			void seed(const ::std::mt19937::result_type& value);

			void setEpsilon(const ::rl::math::Real& epsilon);

			void setFunctionToleranceAbsolute(const ::rl::math::Real& functionToleranceAbsolute);

			void setFunctionToleranceRelative(const ::rl::math::Real& functionToleranceRelative);

			void setLowerBound(const ::rl::math::Vector& lb);

			void setOptimizationToleranceAbsolute(const ::rl::math::Real& optimizationToleranceAbsolute);

			void setOptimizationToleranceAbsolute(const ::rl::math::Vector& optimizationToleranceAbsolute);

			void setOptimizationToleranceRelative(const ::rl::math::Real& optimizationToleranceRelative);

			void setUpperBound(const ::rl::math::Vector& ub);

			bool solve();

		protected:

		private:
			static double f(unsigned int n, const double* x, double* grad, void* data);

			::std::size_t iteration;

			::rl::math::Vector lb;

			::std::unique_ptr<::nlopt_opt_s, decltype(&::nlopt_destroy)> opt;

			::std::uniform_real_distribution<::rl::math::Real> randDistribution;

			::std::mt19937 randEngine;

			::rl::math::Vector ub;
		};
	}
}

ext: h

max_stars_repo_name: Mark-Yeatman/rl

max_issues_repo_name: Mark-Yeatman/rl

max_forks_repo_name: Mark-Yeatman/rl


text:
#ifndef SETTINGSWIDGET_H
#define SETTINGSWIDGET_H

#include <QWidget>

#include "utilities/usersettings.h"

#include <gsl/gsl>

#include <memory>

class QDoubleSpinBox;

namespace Ui {
class DisparitySettingsWidget;
}

class DisparitySettingsWidget : public QWidget {
  Q_OBJECT

 public:
  explicit DisparitySettingsWidget(QWidget* parent = 0);
  ~DisparitySettingsWidget() override;

  void setUserSettings(gsl::not_null<UserSettings*> settings);
  UserSettings getUserSettings();
  void conditionalAutoUpdate();

 signals:
  void settingsUpdated(UserSettings updatedSettings);
  void accepted();
  void rejected();

 private:
  void ensureMinSmallerThanMax(gsl::not_null<QDoubleSpinBox*> min,
                               gsl::not_null<QDoubleSpinBox*> max);

  void ensureMaxLargerThanMin(gsl::not_null<QDoubleSpinBox*> min,
                              gsl::not_null<QDoubleSpinBox*> max);

  std::unique_ptr<Ui::DisparitySettingsWidget> ui;
};

#endif  // SETTINGSWIDGET_H


text:
/**
Copyright (c) 2014, Konstantinos Chatzilygeroudis
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
    in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

#ifndef GEOMETRIC_TOOLS_MATH_VECTOR_H
#define GEOMETRIC_TOOLS_MATH_VECTOR_H

/**
* Includes
**/
#include <iostream>
#include <limits>
#include <cmath>
#include <cstring>
#include <geometric_tools/Misc/Helper.h>
#include <cblas.h>

namespace GeometricTools { namespace Math {

template<unsigned int ROWS, unsigned int COLS>
class Matrix;

/**
* General Vector Class
* Supports N-dimension vectors
**/
template<unsigned int N>
class Vector
{
protected:
    // values of vector
    double values_[N];
    // helper variable for initialization
    unsigned int index_;

    /**
    * Initialize Vector from double values
    * C++11 feature - variadic templates for multiple arguments
    **/
    template<typename... Args>
    void initialize(double h, Args&&... args)
    {
        if(index_>=N)
            index_=0;
        // add first argument to the vector data
        values_[index_] = h;
        index_++;
        // Initialize with rest of arguments
        initialize(std::forward<Args>(args)...);
    }

    /**
    * Initialize Vector from double values
    * C++11 feature - variadic templates for multiple arguments
    * Terminating Case - end of arguments
    **/
    template<typename... Args>
    void initialize()
    {
        index_ = 0;
    }

public:

    /**
    * Default Constructor
    * initialize all data to zero
    **/
    Vector()
    {
        memset(values_,0,N*sizeof(double));
    }

    /**
    * Copy Constructor
    * @param other - Vector to copy from
    **/
    Vector(const Vector& other)
    {
        memcpy(values_,other.values_,N*sizeof(double));
    }

    /**
    * Constructor
    * @param h - list of double values
    **/
    template<typename... Args>
    Vector(double h, Args&&... args)
    {
        index_ = 0;
        memset(values_,0,N*sizeof(double));
        // use recursive initialization
        initialize(h, args...);
    }

    /**
    * Overloading += operator
    * Addition of 2 Vectors
    * @param other - vector to perform addition with
    * @return Vector - self (as the result is saved there)
    **/
    Vector operator+=(const Vector& other)
    {
        cblas_daxpy(N, 1.0, &other.values_[0], 1, &values_[0], 1);
        return *this;
    }

    /**
    * Overloading -= operator
    * Subtraction of 2 Vectors
    * @param other - vector to perform subtraction with
    * @return Vector - self (as the result is saved there)
    **/
    Vector operator-=(const Vector& other)
    {
        cblas_daxpy(N, -1.0, &other.values_[0], 1, &values_[0], 1);
        return *this;
    }

    /**
    * Overloading += operator
    * Addition with scalar (double)
    * @param other - double to add with
    * @return Vector - self (result)
    **/
    Vector operator+=(const double& other)
    {
        Vector tmp;
        tmp.ones();
        cblas_daxpy(N, other, &tmp.values_[0], 1, &values_[0], 1);
        return *this;
    }

    /**
    * Overloading -= operator
    * Subtraction of scalar (double)
    * @param other - double to substract
    * @return Vector - self (result)
    **/
    Vector operator-=(const double& other)
    {
        Vector tmp;
        tmp.ones();
        cblas_daxpy(N, -other, &tmp.values_[0], 1, &values_[0], 1);
        return *this;
    }

    /**
    * Overloading *= operator
    * Multiplication with scalar (double)
    * @param other - double to multiply with
    * @return Vector - self (result)
    **/
    Vector operator*=(const double& other)
    {
        cblas_dscal(N, other, &values_[0], 1);
        return *this;
    }

    /**
    * Overloading /= operator
    * Division with scalar (double) - if zero ignores division (returns self)
    * @param other - double to divide with
    * @return Vector - self (result)
    **/
    Vector operator/=(const double& other)
    {
        if(std::abs(other) < std::numeric_limits<double>::epsilon())
            return (*this);
        cblas_dscal(N, 1.0/other, &values_[0], 1);
        return *this;
    }

    /**
    * Overloading + operator
    * Addition of 2 Vectors
    * @return Vector - the result of the addition
    **/
    Vector operator+(const Vector& lh) const
    {
        Vector t = (*this);
        t += lh;
        return t;
    }

    /**
    * Overloading - operator
    * Subtraction of 2 Vectors
    * @return Vector - the result of the subtraction
    **/
    Vector operator-(const Vector& lh) const
    {
        Vector t = (*this);
        t -= lh;
        return t;
    }

    /**
    * Overloading * operator
    * Multiplication of 2 Vectors (Dot product)
    * @return double - the result of the multiplication
    **/
    double operator*(const Vector& lh) const
    {
        double s = 0.0;
        for(unsigned int i=0;i<N;i++)
            s += (*this)[i]*lh[i];
        return s;
    }

    /**
    * Overloading + operator
    * Addition with scalar (double)
    * @param other - double to add with
    * @return Vector - the result
    **/
    Vector operator+(const double& other) const
    {
        Vector tmp = (*this);
        tmp += other;
        return tmp;
    }

    /**
    * Overloading - operator
    * Subtraction of scalar (double)
    * @param other - double to subtract
    * @return Vector - the result
    **/
    Vector operator-(const double& other) const
    {
        Vector tmp = (*this);
        tmp -= other;
        return tmp;
    }

    /**
    * Overloading * operator
    * Multiplication with scalar (double)
    * @param other - double to multiply with
    * @return Vector - the result
    **/
    Vector operator*(const double& other) const
    {
        Vector tmp = (*this);
        tmp *= other;
        return tmp;
    }

    /**
    * Overloading / operator
    * Division with scalar (double) - if zero ignores division (returns self)
    * @param other - double to divide with
    * @return Vector - the result
    **/
    Vector operator/(const double& other) const
    {
        Vector tmp = (*this);
        tmp /= other;
        return tmp;
    }

    /**
    * Overloading minus (-) operator
    **/
    Vector operator-()
    {
        return -1*(*this);
    }

    /**
    * Overloading == operator
    * @param other - Vector to compare
    * @return bool
    **/
    bool operator==(const Vector& other) const
    {
        Vector tmp = (*this)-other;
        return (tmp.lengthSq()<std::numeric_limits<double>::epsilon());
    }

    /**
    * Overloading != operator
    * @param other - Vector to compare
    * @return bool
    **/
    bool operator!=(const Vector& other) const
    {
        Vector tmp = (*this)-other;
        return (tmp.lengthSq()>=std::numeric_limits<double>::epsilon());
    }

    // !-- THIS NEEDS TO BE REMOVED --! //
    /**
    * Get pointer to values array
    * @return pointer to array
    **/
    double* data()
    {
        return values_;
    }

    /**
    * Get Length of Vector
    * @return double - length
    **/
    double length() const
    {
        return cblas_dnrm2(N, &values_[0], 1);
    }

    /**
    * Set vector to 1s
    **/
    void ones()
    {
        memset(&values_[0], 1, N*sizeof(double));
    }

    /**
    * Get LengthSq of Vector
    * @return double - length squared
    **/
    double lengthSq() const
    {
        double s = cblas_dnrm2(N, &values_[0], 1);
        return s*s;
    }

    /**
    * Normalize Vector
    **/
    void normalize()
    {
        double l = length();
        if(l>std::numeric_limits<double>::epsilon())
            *this /= l;
    }

    /**
    * Normalized Vector
    **/
    Vector normalized()
    {
        Vector tmp = Vector(*this);
        tmp.normalize();
        return tmp;
    }

    /**
    * Overloading () operator
    * Access Vector Matlab-like
    * @param i - index to return
    * @return double - value of i-th element
    **/
    double& operator()(int i) //needs assert legal index
    {
        return values_[i];
    }

    /**
    * Overloading () operator - const version
    * Access Vector Matlab-like
    * @param i - index to return
    * @return double - value of i-th element
    **/
    double operator()(int i) const //needs assert legal index
    {
        return values_[i];
    }

    /**
    * Overloading [] operator
    * Access Vector Array-like
    * @param i - index to return
    * @return double - value of i-th element
    **/
    double& operator[](int i) //assert legal index
    {
        return values_[i];
    }

    /**
    * Overloading [] operator - const version
    * Access Vector Array-like
    * @param i - index to return
    * @return double - value of i-th element
    **/
    double operator[](int i) const //assert legal index
    {
        return values_[i];
    }

    /**
    * Get ith unit vector with size N
    * @param i
    * @return Vector - unit vector
    **/
    static Vector e(const unsigned int& i)
    {
        Vector k;
        k[i] = 1;
        return k;
    }

    /**
    * Destructor
    **/
    ~Vector(void)
    {
    }

    template<unsigned int ROWS, unsigned int COLS>
    friend class Matrix;
};

/**
* Cross Product
* Applies only to 3D Vectors
* @return Vector - the result of the cross product
**/
inline Vector<3> cross(const Vector<3>& rh, const Vector<3>& lh)
{
    return Vector<3>(rh[1]*lh[2]-rh[2]*lh[1], rh[2]*lh[0]-rh[0]*lh[2], rh[0]*lh[1]-rh[1]*lh[0]);
}

/**
* Projection of a to e
* @return Vector - the result of the cross product
**/
template <unsigned int N>
Vector<N> projection(const Vector<N>& a, const Vector<N>& e)
{
    return ((e*a)*e/(e*e));
}

/**
* Overloading << operator
* "print" vector to stream
* @param ostream - stream to print the vector to
* @param Vector - vector to print
**/
template <unsigned int N>
std::ostream& operator<<(std::ostream& os, const Vector<N>& obj)
{
    for(unsigned int i=0;i<N-1;i++)
        os<<obj[i]<<" ";
    os<<obj[N-1];
    return os;
}

/**
* Overloading >> operator
* read vector from stream
* @param istream - stream to read the vector from
* @param Vector - vector to read
**/
template <unsigned int N>
std::istream& operator>>(std::istream& in, Vector<N>& obj)
{
    for(unsigned int i=0;i<N;i++)
        in>>obj[i];
    return in;
}

/**
* Overloading / operator
* Division with scalar (double)
* Perform Vector / scalar (as opposed to Vector / scalar inside Class)
**/
template <unsigned int N>
Vector<N> operator/(const double& a, const Vector<N>& b)
{
    if(std::abs(a) < std::numeric_limits<double>::epsilon())
        return Vector<N>();
    Vector<N> tmp = Vector<N>(b);
    for(unsigned int i=0;i<N;i++) {
        if(std::abs(tmp[i]) < std::numeric_limits<double>::epsilon())
            return b;
        tmp[i] = a/tmp[i];
    }
    return tmp;
}

/**
* Overloading * operator
* Multiplication with scalar (double)
* Perform scalar * Vector (as opposed to Vector * scalar inside Class)
**/
template <unsigned int N>
Vector<N> operator*(const double& a, const Vector<N>& b)
{
    return b*a;
}

/**
* Typedefs for frequently used types
**/
typedef Vector<2> Vector2;
typedef Vector<3> Vector3;
typedef Vector<4> Vector4;

} }

#endif

max_stars_repo_name: costashatz/GeometricTools

max_issues_repo_name: costashatz/GeometricTools

max_forks_repo_name: costashatz/GeometricTools


text:
/*
 * mcmc_lotkavolterra.c
 *
 *  Created on: 15/11/2015
 *      Author: Laura Ferrer
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#define USAGE "./mcmc_lotkavolterra.x n_steps n_burn"

void leer(double *tiempo, double *presa, double *depredador, int n_puntos);
double* iniciar(int n_puntos);

int main (int argc, char **argv)
{
	int i=0;
	int lineas = 0;
	int iteraciones = atof(argv[2])+atof(argv[1]);
	int corte = atof(argv[2]);

	double a = 1;
	double b = 1;
	double c = 1;
	double d = 1;

	double a2;
	double b2;
	double c2;
	double d2;

	FILE *file;
	file = fopen("lotka_volterra_obs.dat", "r");

	while(!feof(file)) //Cuenta la cantidad de datos provistos.
	{
  		char ch = fgetc(file);
  		if(ch == '\n')
  		{
    			lineas++;
  		}
	}

	fclose(file);

	lineas --;// menos la primera línea

	double *x = iniciar(lineas);
	double *y= iniciar(lineas);
	double *x_real=	iniciar(lineas);
	double *y_real = iniciar(lineas);
	double *t = iniciar(lineas);
	double *lay = iniciar(lineas);
	double *lax = iniciar(lineas);

	leer(t,x_real,y_real,lineas);
	lay[0]=y_real[0];
	lax[0]=x_real[0];

	double parecido (double modo)
	{
		i = 0;
		double suma=0;
		if (modo == 1)
		{

			for (i = 0; i < lineas; i += 1)
			{
				suma += pow(x[i]-y_real[i],2.0);
				suma += pow(y[i]-x_real[i],2.0);
			}

		}

		if (modo == 2)
		{

			for (i = 0; i < lineas; i += 1)
			{
				suma += pow(lax[i]-y_real[i],2.0);
				suma += pow(lay[i]-x_real[i],2.0);
			}
		}

		return (1.0/2.0)*suma;
	}

	double dx (double x, double y, double la, double lb)
	{
		double dx = x*(la-lb*y);
		return dx;
	}

	double dy (double x, double y, double lc, double ld)
	{
		double dy = -y*(lc-ld*x);
		return dy;
	}

	void kutta4 (double la, double lb, double lc, double ld)
	{

		double h = t[1]-t[0];
		i = 1;

		for (i = 1; i < lineas; i += 1)
		{
			//Inicio
			double kx1 = dx(lax[i-1],lay[i-1],la,lb);
			double ky1 = dy(lax[i-1],lay[i-1],lc,ld);

			//paso 1
			double x1 = lax[i-1] + (h/2.0)*kx1;
			double y1 = lay[i-1] + (h/2.0)*ky1;

			double kx2 = dx(x1,y1,la,lb);
			double ky2 = dy(x1,y1,lc,ld);

			//paso 2
			double x2 = lax[i-1] + (h/2.0)*kx2;
			double y2 = lay[i-1] + (h/2.0)*ky2;

			double kx3 = dx(x2,y2,la,lb);
			double ky3 = dy(x2,y2,lc,ld);

			//paso 3
			double x3 = lax[i-1] + h*kx3;
			double y3 = lay[i-1] + h*ky3;

			double kx4 = dx(x3,y3,la,lb);
			double ky4 = dy(x3,y3,lc,ld);

			//paso 4

			double mx = (1.0/6.0)*(kx1 + 2.0*kx2+2.0*kx3+kx4);
			double my = (1.0/6.0)*(ky1 + 2.0*ky2+2.0*ky3+ky4);

			lax[i]= lax[i-1] + h*mx;
			lay[i]= lay[i-1] + h*my;

		}
	}

	void mcmc()
	{
		int k = 1;
		for (k = 1; k < iteraciones; k++)
		{
    			const gsl_rng_type * T;
    			gsl_rng * r;
   			gsl_rng_env_setup();
    			T = gsl_rng_default;
   			r = gsl_rng_alloc (T);

			a2 = a + (2*gsl_ran_gaussian(r,drand48())+1);
			srand((unsigned)time(NULL));
			b2 = b + (2*gsl_ran_gaussian(r,drand48())+1);
			srand((unsigned)time(NULL));
			c2 = c + (2*gsl_ran_gaussian(r,drand48())+1);
			srand((unsigned)time(NULL));
			d2 = d + (2*gsl_ran_gaussian(r,drand48())+1);
			srand((unsigned)time(NULL));

			kutta4(a,b,c,d);

			int j =0;

			for (j = 0; j < lineas; j++) // Copia las listas
			{
     				x[j] = lax[j];
				y[j] = lay[j];
   			}

			kutta4(a2,b2,c2,d2);

			// Calculo de los errores y similitudes
			double difvieja = parecido(1);
			double difnueva = parecido(2);

			if (difnueva < difvieja)
			{
				a=a2;
        	    		b=b2;
        	   		c=c2;
        	    		d=d2;
				if (k>corte) {printf ("%g,%g,%g,%g\n",a,b,c,d);}
			}
			else
			{

				srand((unsigned)time(NULL));
				double alfa = difvieja/difnueva;
				double beta = drand48();

				if (beta >= alfa)
				{
					a=a2;
        	    			b=b2;
        	   			c=c2;
        	    			d=d2;
					if (k>corte) {printf ("%g,%g,%g,%g\n",a,b,c,d);}
				}
				else if (k>corte)
				{
					printf ("%g,%g,%g,%g\n",a,b,c,d);
				}
			}
		}
	}

	mcmc();
	return 0;
}

void leer(double *tiempo, double *presa, double *depredador, int n_puntos)
{
	FILE *file;
	int j;
	file = fopen("lotka_volterra_obs.dat", "r");
	rewind(file);
	fscanf(file,"%*[^\n]\n"); //Lee cualquier cosa en la primera línea
	for(j=0;j<n_puntos;j++)
	{
		fscanf(file, "%lf %lf %lf\n", &tiempo[j], &presa[j], &depredador[j]);
	}
	fclose(file);
}

double* iniciar(int n_puntos)
{
	double *array;
	int i;
	if(!(array = malloc(n_puntos * sizeof(double))))
	{
    		printf("Problema en reserva\n");
    		exit(1);
  	}
  	for(i=0;i<n_puntos;i++)
	{
  	array[i] = 0.0;
  	}
  return array;
}

ext: c


text:
#include <err.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv2.h>

#define X   y[0]
#define V_X y[1]
#define Y   y[2]
#define V_Y y[3]

const double g = 9.81;        /* m/s^2 */
const double v_0 = 700.0;     /* m/s */
const double B2_m = 4.0e-5;   /* 1/m */
const double y_d = 1.0e4;     /* m */

int func(double t, const double y[], double f[], void *params);

int main(int argc, char *argv[]) {
    gsl_odeiv2_system sys = {func, NULL, 4, NULL};
    gsl_odeiv2_driver *driver = gsl_odeiv2_driver_alloc_y_new(
            &sys, gsl_odeiv2_step_rkf45, 1.0e-6, 1.0e-6, 0.0
    );
    int i = 1;
    double t = 0.0;
    double alpha = argc > 1 ? strtod(argv[1], NULL) : 1.0;
    double y[4];
    X = Y = 0.0;
    V_X = v_0*cos(alpha);
    V_Y = v_0*sin(alpha);
    while (Y >= 0.0) {
        double t_i = i/50.0;
        int status = gsl_odeiv2_driver_apply(driver, &t, t_i, y);
        if (status != GSL_SUCCESS) {
            warnx("apply status = %d", status);
            break;
        }
        printf("%.12le %.12le %.12le %.12le %.12le\n", t, X, Y, V_X, V_Y);
        i++;
    }
    gsl_odeiv2_driver_free(driver);
    return EXIT_SUCCESS;
}

#define DX_DT f[0]
#define DVX_DT f[1]
#define DY_DT f[2]
#define DVY_DT f[3]

int func(double t, const double y[], double f[], void *params) {
    double v = sqrt(V_X*V_X + V_Y*V_Y);
    double corr = exp(-Y/y_d);
    DX_DT  = V_X;
    DVX_DT = -B2_m*corr*v*V_X;
    DY_DT  = V_Y;
    DVY_DT = -g - B2_m*corr*v*V_Y;
    return GSL_SUCCESS;
}

max_stars_repo_name: Gjacquenot/training-material

max_issues_repo_name: Gjacquenot/training-material

max_forks_repo_name: Gjacquenot/training-material


text:
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file oaisim.c
 * \brief oaisim top level
 * \author Navid Nikaein
 * \date 2013-2015
 * \version 1.0
 * \company Eurecom
 * \email: openair_tech@eurecom.fr
 * \note
 * \warning
 */

#include <string.h>
#include <math.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cblas.h>
#include <execinfo.h>

#include "event_handler.h"
#include "SIMULATION/RF/defs.h"
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/LTE_TRANSPORT/proto.h"
#include "PHY/vars.h"

#include "SIMULATION/ETH_TRANSPORT/proto.h"

//#ifdef OPENAIR2
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/vars.h"
#include "pdcp.h"
#include "RRC/LITE/vars.h"
#include "RRC/NAS/nas_config.h"

#include "SCHED/defs.h"
#include "SCHED/vars.h"
#include "system.h"

#include "PHY/TOOLS/lte_phy_scope.h"

#ifdef SMBV
// Rohde&Schwarz SMBV100A vector signal generator
#include "PHY/TOOLS/smbv.h"
char smbv_fname[] = "smbv_config_file.smbv";
unsigned short smbv_nframes = 4; // how many frames to configure 1,..,4
unsigned short config_frames[4] = {2,9,11,13};
unsigned char smbv_frame_cnt = 0;
uint8_t config_smbv = 0;
char smbv_ip[16];
#endif

#if defined(FLEXRAN_AGENT_SB_IF)
#   include "flexran_agent.h"
#endif

#include "oaisim_functions.h"

#include "oaisim.h"
#include "oaisim_config.h"
#include "UTIL/OCG/OCG_extern.h"
#include "cor_SF_sim.h"
#include "UTIL/OMG/omg_constants.h"
#include "UTIL/FIFO/pad_list.h"
#include "enb_app.h"

#include "../PROC/interface.h"
#include "../PROC/channel_sim_proc.h"
#include "../PROC/Tsync.h"
#include "../PROC/Process.h"

#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OTG/otg_kpi.h"
#include "assertions.h"

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
# include "create_tasks.h"
#endif

#include "T.h"

/*
  DCI0_5MHz_TDD0_t          UL_alloc_pdu;
  DCI1A_5MHz_TDD_1_6_t      CCCH_alloc_pdu;
  DCI2_5MHz_2A_L10PRB_TDD_t DLSCH_alloc_pdu1;
  DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2;
*/

#define UL_RB_ALLOC            computeRIV(lte_frame_parms->N_RB_UL,0,24)
#define CCCH_RB_ALLOC          computeRIV(lte_frame_parms->N_RB_UL,0,3)
#define RA_RB_ALLOC            computeRIV(lte_frame_parms->N_RB_UL,0,3)
#define DLSCH_RB_ALLOC         0x1fff

#define DECOR_DIST             100
#define SF_VAR                 10

//constant for OAISIM soft realtime calibration
//#define SF_DEVIATION_OFFSET_NS 100000        /*= 0.1ms : should be as a number of UE */
//#define SLEEP_STEP_US          100           /*  = 0.01ms could be adaptive, should be as a number of UE */
//#define K                      2             /* averaging coefficient */
//#define TARGET_SF_TIME_NS      1000000       /* 1ms = 1000000 ns */

uint8_t usim_test = 0;

frame_t frame = 0;
char stats_buffer[16384];
channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs];
channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
//Added for PHY abstraction
node_desc_t *enb_data[NUMBER_OF_eNB_MAX];
node_desc_t *ue_data[NUMBER_OF_UE_MAX];

pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1;

pthread_mutex_t subframe_mutex;
int subframe_eNB_mask=0,subframe_UE_mask=0;

openair0_config_t openair0_cfg[MAX_CARDS];
uint32_t          downlink_frequency[MAX_NUM_CCs][4];
int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];
openair0_rf_map rf_map[MAX_NUM_CCs];

#if defined(ENABLE_ITTI)
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
#endif
volatile int                    oai_exit = 0;

//int32_t **rxdata;
//int32_t **txdata;

// Added for PHY abstraction
extern node_list* ue_node_list;
extern node_list* enb_node_list;
extern int pdcp_period, omg_period;

extern double **s_re, **s_im, **r_re, **r_im, **r_re0, **r_im0;
int map1, map2;
extern double **ShaF;
double snr_dB, sinr_dB, snr_direction; //,sinr_direction;
extern double snr_step;
extern uint8_t set_sinr;
extern uint8_t ue_connection_test;
extern uint8_t set_seed;
extern uint8_t target_dl_mcs;
extern uint8_t target_ul_mcs;
extern uint8_t abstraction_flag;
extern uint8_t ethernet_flag;
extern uint16_t Nid_cell;

extern LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];

double cpuf;
#include "threads_t.h"
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};

//#ifdef XFORMS
int otg_enabled;
int xforms=0;
//#endif

time_stats_t oaisim_stats;
time_stats_t oaisim_stats_f;
time_stats_t dl_chan_stats;
time_stats_t ul_chan_stats;

// this should reflect the channel models in openair1/SIMULATION/TOOLS/defs.h
mapping small_scale_names[] = {
  { "custom", custom }, { "SCM_A", SCM_A },
  { "SCM_B", SCM_B   }, { "SCM_C", SCM_C },
  { "SCM_D", SCM_D   }, { "EPA",   EPA   },
  { "EVA",   EVA     }, { "ETU",   ETU   },
  { "MBSFN", MBSFN },   { "Rayleigh8", Rayleigh8 },
  { "Rayleigh1", Rayleigh1 }, { "Rayleigh1_800", Rayleigh1_800 },
  { "Rayleigh1_corr", Rayleigh1_corr }, { "Rayleigh1_anticorr", Rayleigh1_anticorr },
  { "Rice8", Rice8 }, { "Rice1", Rice1 }, { "Rice1_corr", Rice1_corr },
  { "Rice1_anticorr", Rice1_anticorr }, { "AWGN", AWGN }, { NULL,-1 }
};
#if !defined(ENABLE_ITTI)
static void *
sigh (void *arg);
#endif
void
oai_shutdown (void);

void reset_opp_meas_oaisim (void);

void
help (void)
{
  printf ("Usage: oaisim -h -a -F -C tdd_config -K [log_file] -V [vcd_file] -R N_RB_DL -e -x transmission_mode -m target_dl_mcs -r(ate_adaptation) -n n_frames -s snr_dB -k ricean_factor -t max_delay -f forgetting factor -A channel_model -z cooperation_flag -u nb_local_ue -U UE mobility -b nb_local_enb -B eNB_mobility -M ethernet_flag -p nb_master -g multicast_group -l log_level -c ocg_enable -T traffic model -D multicast network device\n");

  printf ("-h provides this help message!\n");
  printf ("-a Activates PHY abstraction mode\n");
  printf ("-A set the multipath channel simulation,  options are: SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr,Rayleigh1_anticorr, Rice8,, Rice1, AWGN \n");
  printf ("-b Set the number of local eNB\n");
  printf ("-B Set the mobility model for eNB, options are: STATIC, RWP, RWALK, \n");
  printf ("-c [1,2,3,4] Activate the config generator (OCG) to process the scenario descriptor, or give the scenario manually: -c template_1.xml \n");
  printf ("-C [0-6] Sets TDD configuration\n");
  printf ("-e Activates extended prefix mode\n");
  printf ("-E Random number generator seed\n");
  printf ("-f Set the forgetting factor for time-variation\n");
  printf ("-F Activates FDD transmission (TDD is default)\n");
  printf ("-g Set multicast group ID (0,1,2,3) - valid if M is set\n");
  printf ("-G Enable background traffic \n");
  printf ("-H Enable handover operation (default disabled) \n");
  printf ("-I Enable CLI interface (to connect use telnet localhost 1352)\n");
  printf ("-k Set the Ricean factor (linear)\n");
  printf ("-K [log_file] Enable ITTI logging into log_file\n");
  printf ("-l Set the global log level (8:trace, 7:debug, 6:info, 4:warn, 3:error) \n");
  printf ("-L [0-1] 0 to disable new link adaptation, 1 to enable new link adapatation\n");
  printf ("-m Gives a fixed DL mcs for eNB scheduler\n");
  printf ("-M Set the machine ID for Ethernet-based emulation\n");
  printf ("-n Set the number of frames for the simulation. 0 for no limit\n");
  printf ("-O [enb_conf_file] eNB configuration file name\n");
  printf ("-p Set the total number of machine in emulation - valid if M is set\n");
  printf ("-P [trace type] Enable protocol analyzer. Possible values for OPT:\n");
  printf ("    - wireshark: Enable tracing of layers above PHY using an UDP socket\n");
  printf ("    - pcap:      Enable tracing of layers above PHY to a pcap file\n");
  printf ("    - tshark:    Not implemented yet\n");
  printf ("-q Enable Openair performance profiler \n");
  printf ("-Q Activate and set the MBMS service: 0 : not used (default eMBMS disabled), 1: eMBMS and RRC Connection enabled, 2: eMBMS relaying and RRC Connection enabled, 3: eMBMS enabled, RRC Connection disabled, 4: eMBMS relaying enabled, RRC Connection disabled\n");
  printf ("-R [6,15,25,50,75,100] Sets N_RB_DL\n");
  printf ("-r Activates rate adaptation (DL for now)\n");
  printf ("-s snr_dB set a fixed (average) SNR, this deactivates the openair channel model generator (OCM)\n");
  printf ("-S snir_dB set a fixed (average) SNIR, this deactivates the openair channel model generator (OCM)\n");
  printf ("-t Gives a fixed UL mcs for eNB scheduler\n");
  printf ("-T activate the traffic generator. Valide options are m2m,scbr,mcbr,bcbr,auto_pilot,bicycle_race,open_arena,team_fortress,m2m_traffic,auto_pilot_l,auto_pilot_m,auto_pilot_h,auto_pilot_e,virtual_game_l,virtual_game_m,virtual_game_h,virtual_game_f,alarm_humidity,alarm_smoke,alarm_temperature,openarena_dl,openarena_ul,voip_g711,voip_g729,video_vbr_10mbps,video_vbr_4mbps,video_vbr_2mbp,video_vbr_768kbps,video_vbr_384kbps,video_vbr_192kpbs,background_users\n");
  printf ("-u Set the number of local UE\n");
  printf ("-U Set the mobility model for UE, options are: STATIC, RWP, RWALK\n");
  printf ("-V [vcd_file] Enable VCD dump into vcd_file\n");
  printf ("-w number of CBA groups, if not specified or zero, CBA is inactive\n");
#ifdef SMBV
  printf ("-W IP address to connect to Rohde&Schwarz SMBV100A and configure SMBV from config file. -W0 uses default IP 192.168.12.201\n");
#else
  printf ("-W [Rohde&Schwarz SMBV100A functions disabled. Recompile with SMBV=1]\n");
#endif
  printf ("-x deprecated. Set the transmission mode in config file!\n");
  printf ("-y Set the number of receive antennas at the UE (1 or 2)\n");
  printf ("-Y Set the global log verbosity (none, low, medium, high, full) \n");
  printf ("-z Set the cooperation flag (0 for no cooperation, 1 for delay diversity and 2 for distributed alamouti\n");
  printf ("-Z Reserved\n");
  printf ("--xforms Activate the grapical scope\n");

#if T_TRACER
  printf ("--T_port [port]    use given port\n");
  printf ("--T_nowait         don't wait for tracer, start immediately\n");
  printf ("--T_dont_fork      to ease debugging with gdb\n");
#endif
}

pthread_t log_thread;

void
log_thread_init (void)
{
  //create log_list
  //log_list_init(&log_list);
#ifndef LOG_NO_THREAD

  log_shutdown = 0;

  if ((pthread_mutex_init (&log_lock, NULL) != 0)
      || (pthread_cond_init (&log_notify, NULL) != 0)) {
    return;
  }

  if (pthread_create (&log_thread, NULL, log_thread_function, (void*) NULL)
      != 0) {
    log_thread_finalize ();
    return;
  }

#endif

}

//Call it after the last LOG call
int
log_thread_finalize (void)
{
  int err = 0;

#ifndef LOG_NO_THREAD

  if (pthread_mutex_lock (&log_lock) != 0) {
    return -1;
  }

  log_shutdown = 1;

  /* Wake up LOG thread */
  if ((pthread_cond_broadcast (&log_notify) != 0)
      || (pthread_mutex_unlock (&log_lock) != 0)) {
    err = -1;
  }

  if (pthread_join (log_thread, NULL) != 0) {
    err = -1;
  }

  if (pthread_mutex_unlock (&log_lock) != 0) {
    err = -1;
  }

  if (!err) {
    //log_list_free(&log_list);
    pthread_mutex_lock (&log_lock);
    pthread_mutex_destroy (&log_lock);
    pthread_cond_destroy (&log_notify);
  }

#endif

  return err;
}

#if defined(ENABLE_ITTI)
static void set_cli_start(module_id_t module_idP, uint8_t start)
{
  if (module_idP < NB_eNB_INST) {
    oai_emulation.info.cli_start_enb[module_idP] = start;
  } else {
    oai_emulation.info.cli_start_ue[module_idP - NB_eNB_INST] = start;
  }
}
#endif

#ifdef OPENAIR2
int omv_write(int pfd, node_list* enb_node_list, node_list* ue_node_list, Data_Flow_Unit omv_data)
{
  module_id_t i, j;
  omv_data.end = 0;

  //omv_data.total_num_nodes = NB_UE_INST + NB_eNB_INST;
  for (i = 0; i < NB_eNB_INST; i++) {
    if (enb_node_list != NULL) {
      omv_data.geo[i].x = (enb_node_list->node->x_pos < 0.0) ? 0.0 : enb_node_list->node->x_pos;
      omv_data.geo[i].y = (enb_node_list->node->y_pos < 0.0) ? 0.0 : enb_node_list->node->y_pos;
      omv_data.geo[i].z = 1.0;
      omv_data.geo[i].mobility_type = oai_emulation.info.omg_model_enb;
      omv_data.geo[i].node_type = 0; //eNB
      enb_node_list = enb_node_list->next;
      omv_data.geo[i].Neighbors = 0;

      for (j = NB_eNB_INST; j < NB_UE_INST + NB_eNB_INST; j++) {
        if (is_UE_active (i, j - NB_eNB_INST) == 1) {
          omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j;
          omv_data.geo[i].Neighbors++;
          LOG_D(
		OMG,
		"[eNB %d][UE %d] is_UE_active(i,j) %d geo (x%d, y%d) num neighbors %d\n", i, j-NB_eNB_INST, is_UE_active(i,j-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors);
        }
      }
    }
  }

  for (i = NB_eNB_INST; i < NB_UE_INST + NB_eNB_INST; i++) {
    if (ue_node_list != NULL) {
      omv_data.geo[i].x = (ue_node_list->node->x_pos < 0.0) ? 0.0 : ue_node_list->node->x_pos;
      omv_data.geo[i].y = (ue_node_list->node->y_pos < 0.0) ? 0.0 : ue_node_list->node->y_pos;
      omv_data.geo[i].z = 1.0;
      omv_data.geo[i].mobility_type = oai_emulation.info.omg_model_ue;
      omv_data.geo[i].node_type = 1; //UE
      //trial
      omv_data.geo[i].state = 1;
      omv_data.geo[i].rnti = 88;
      omv_data.geo[i].connected_eNB = 0;
      omv_data.geo[i].RSRP = 66;
      omv_data.geo[i].RSRQ = 55;
      omv_data.geo[i].Pathloss = 44;
      omv_data.geo[i].RSSI[0] = 33;
      omv_data.geo[i].RSSI[1] = 22;

      if ((sizeof(omv_data.geo[0].RSSI) / sizeof(omv_data.geo[0].RSSI[0])) > 2) {
        omv_data.geo[i].RSSI[2] = 11;
      }

      ue_node_list = ue_node_list->next;
      omv_data.geo[i].Neighbors = 0;

      for (j = 0; j < NB_eNB_INST; j++) {
        if (is_UE_active (j, i - NB_eNB_INST) == 1) {
          omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j;
          omv_data.geo[i].Neighbors++;
          LOG_D(
		OMG,
		"[UE %d][eNB %d] is_UE_active  %d geo (x%d, y%d) num neighbors %d\n", i-NB_eNB_INST, j, is_UE_active(j,i-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors);
        }
      }
    }
  }

  LOG_E(OMG, "pfd %d \n", pfd);

  if (write (pfd, &omv_data, sizeof(struct Data_Flow_Unit)) == -1)
    perror ("write omv failed");

  return 1;
}

void omv_end(int pfd, Data_Flow_Unit omv_data)
{
  omv_data.end = 1;

  if (write (pfd, &omv_data, sizeof(struct Data_Flow_Unit)) == -1)
    perror ("write omv failed");
}
#endif

#ifdef OPENAIR2
int pfd[2]; // fd for omv : fixme: this could be a local var
#endif

#ifdef OPENAIR2
static Data_Flow_Unit omv_data;
#endif //ALU
static module_id_t UE_inst = 0;
static module_id_t eNB_inst = 0;

Packet_OTG_List_t *otg_pdcp_buffer;

typedef enum l2l1_task_state_e {
  L2L1_WAITTING, L2L1_RUNNING, L2L1_TERMINATED,
} l2l1_task_state_t;

l2l1_task_state_t l2l1_state = L2L1_WAITTING;

extern openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
extern openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
extern openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
extern openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];

/*------------------------------------------------------------------------------*/
void *
l2l1_task (void *args_p)
{

  int CC_id;

  // Framing variables
  int32_t sf;

  //char fname[64], vname[64];

  //#ifdef XFORMS
  // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
  // at eNB 0, an UL scope for every UE
  FD_lte_phy_scope_ue *form_ue[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  FD_lte_phy_scope_enb *form_enb[NUMBER_OF_UE_MAX];
  char title[255];
  char xname[32] = "oaisim";
  int xargc = 1;
  char *xargv[1];
  //#endif

#undef PRINT_STATS /* this undef is to avoid gcc warnings */
#define PRINT_STATS
#ifdef PRINT_STATS
  int len;
  FILE *UE_stats[NUMBER_OF_UE_MAX];
  FILE *UE_stats_th[NUMBER_OF_UE_MAX];
  FILE *eNB_stats[NUMBER_OF_eNB_MAX];
  FILE *eNB_avg_thr;
  FILE *eNB_l2_stats;
  char UE_stats_filename[255];
  char eNB_stats_filename[255];
  char UE_stats_th_filename[255];
  char eNB_stats_th_filename[255];
#endif

  if (xforms==1) {
    xargv[0] = xname;
    fl_initialize (&xargc, xargv, NULL, 0, 0);
    eNB_inst = 0;
    for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) {
      for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
	// DL scope at UEs
	form_ue[CC_id][UE_inst] = create_lte_phy_scope_ue();
	sprintf (title, "LTE DL SCOPE eNB %d to UE %d CC_id %d", eNB_inst, UE_inst, CC_id);
	fl_show_form (form_ue[CC_id][UE_inst]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);

	if (PHY_vars_UE_g[UE_inst][CC_id]->use_ia_receiver == 1) {
	  fl_set_button(form_ue[CC_id][UE_inst]->button_0,1);
	  fl_set_object_label(form_ue[CC_id][UE_inst]->button_0, "IA Receiver ON");
	  fl_set_object_color(form_ue[CC_id][UE_inst]->button_0, FL_GREEN, FL_GREEN);
	}

      }
      // UL scope at eNB 0
      form_enb[UE_inst] = create_lte_phy_scope_enb();
      sprintf (title, "LTE UL SCOPE UE %d to eNB %d", UE_inst, eNB_inst);
      fl_show_form (form_enb[UE_inst]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);

    }
  }

#ifdef PRINT_STATS

  for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
    sprintf(UE_stats_filename,"UE_stats%d.txt",UE_inst);
    UE_stats[UE_inst] = fopen (UE_stats_filename, "w");
  }

  for (eNB_inst=0; eNB_inst<NB_eNB_INST; eNB_inst++) {
    sprintf(eNB_stats_filename,"eNB_stats%d.txt",eNB_inst);
    eNB_stats[eNB_inst] = fopen (eNB_stats_filename, "w");
  }

  if(abstraction_flag==0) {
    for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
      /* TODO: transmission_mode is defined per CC, we set 0 for now */
      sprintf(UE_stats_th_filename,"UE_stats_th%d_tx%d.txt",UE_inst,oai_emulation.info.transmission_mode[0]);
      UE_stats_th[UE_inst] = fopen (UE_stats_th_filename, "w");
    }

    /* TODO: transmission_mode is defined per CC, we set 0 for now */
    sprintf(eNB_stats_th_filename,"eNB_stats_th_tx%d.txt",oai_emulation.info.transmission_mode[0]);
    eNB_avg_thr = fopen (eNB_stats_th_filename, "w");
  } else {
    for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
      /* TODO: transmission_mode is defined per CC, we set 0 for now */
      sprintf(UE_stats_th_filename,"UE_stats_abs_th%d_tx%d.txt",UE_inst,oai_emulation.info.transmission_mode[0]);
      UE_stats_th[UE_inst] = fopen (UE_stats_th_filename, "w");
    }

    /* TODO: transmission_mode is defined per CC, we set 0 for now */
    sprintf(eNB_stats_th_filename,"eNB_stats_abs_th_tx%d.txt",oai_emulation.info.transmission_mode[0]);
    eNB_avg_thr = fopen (eNB_stats_th_filename, "w");
  }

#ifdef OPENAIR2
  eNB_l2_stats = fopen ("eNB_l2_stats.txt", "w");
  LOG_I(EMU,"eNB_l2_stats=%p\n", eNB_l2_stats);
#endif

#endif

#if defined(ENABLE_ITTI)
  MessageDef *message_p = NULL;
  const char *msg_name = NULL;
  int result;

  itti_mark_task_ready (TASK_L2L1);
  LOG_I(EMU, "TASK_L2L1 is READY\n");

  if ((oai_emulation.info.nb_enb_local > 0) &&
      (oai_emulation.info.node_function[0] < NGFI_RAU_IF4p5)) {
    /* Wait for the initialize message */
    do {
      if (message_p != NULL) {
        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }

      itti_receive_msg (TASK_L2L1, &message_p);
      msg_name = ITTI_MSG_NAME (message_p);
      LOG_I(EMU, "TASK_L2L1 received %s in state L2L1_WAITTING\n", msg_name);

      switch (ITTI_MSG_ID(message_p)) {
      case INITIALIZE_MESSAGE:
        l2l1_state = L2L1_RUNNING;
        start_eNB = 1;
        break;

      case ACTIVATE_MESSAGE:
        set_cli_start(ITTI_MSG_INSTANCE (message_p), 1);
        break;

      case DEACTIVATE_MESSAGE:
        set_cli_start(ITTI_MSG_INSTANCE (message_p), 0);
        break;

      case TERMINATE_MESSAGE:
        l2l1_state = L2L1_TERMINATED;
        break;

      default:
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
      }
    } while (l2l1_state == L2L1_WAITTING);

    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }

#endif
  module_id_t enb_id;
  module_id_t UE_id;
  for (enb_id = 0; enb_id < NB_eNB_INST; enb_id++)
    mac_xface->mrbch_phy_sync_failure (enb_id, 0, enb_id);

  if (abstraction_flag == 1) {
    for (UE_id = 0; UE_id < NB_UE_INST; UE_id++)
      mac_xface->dl_phy_sync_success (UE_id, 0, 0,1);   //UE_id%NB_eNB_INST);
  }

  start_meas (&oaisim_stats);

  for (frame = 0;
       (l2l1_state != L2L1_TERMINATED) &&
	 ((oai_emulation.info.n_frames_flag == 0) ||
	  (frame < oai_emulation.info.n_frames));
       frame++) {

#if defined(ENABLE_ITTI)

    do {
      // Checks if a message has been sent to L2L1 task
      itti_poll_msg (TASK_L2L1, &message_p);

      if (message_p != NULL) {
        msg_name = ITTI_MSG_NAME (message_p);
        LOG_I(EMU, "TASK_L2L1 received %s\n", msg_name);

        switch (ITTI_MSG_ID(message_p)) {
        case ACTIVATE_MESSAGE:
          set_cli_start(ITTI_MSG_INSTANCE (message_p), 1);
          break;

        case DEACTIVATE_MESSAGE:
          set_cli_start(ITTI_MSG_INSTANCE (message_p), 0);
          break;

        case TERMINATE_MESSAGE:
          l2l1_state = L2L1_TERMINATED;
          break;

        case MESSAGE_TEST:
          break;

        default:
          LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
          break;
        }

        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }
    } while(message_p != NULL);

#endif

    //Run the aperiodic user-defined events
    if (oai_emulation.info.oeh_enabled == 1)
      execute_events (frame);

    if (ue_connection_test == 1) {
      if ((frame % 20) == 0) {
        snr_dB += snr_direction;
        sinr_dB -= snr_direction;
      }

      if (snr_dB == -20) {
        snr_direction = snr_step;
      } else if (snr_dB == 20) {
        snr_direction = -snr_step;
      }
    }

    oai_emulation.info.frame = frame;
    //oai_emulation.info.time_ms += 1;
    oai_emulation.info.time_s += 0.01; // emu time in s, each frame lasts for 10 ms // JNote: TODO check the coherency of the time and frame (I corrected it to 10 (instead of 0.01)

     update_omg (frame); // frequency is defined in the omg_global params configurable by the user
    update_omg_ocm ();

#ifdef OPENAIR2

    // check if pipe is still open
    if ((oai_emulation.info.omv_enabled == 1)) {
      omv_write (pfd[1], enb_node_list, ue_node_list, omv_data);
    }

#endif

    update_ocm ();

    for (sf = 0; sf < 10; sf++) {
      LOG_D(EMU,"************************* Subframe %d\n",sf);

      start_meas (&oaisim_stats_f);

      wait_for_slot_isr ();

#if defined(ENABLE_ITTI)
      itti_update_lte_time(frame % MAX_FRAME_NUMBER, sf<<1);
#endif

      oai_emulation.info.time_ms = frame * 10 + sf;

#ifdef PROC

    if(Channel_Flag==1)
      Channel_Func(s_re2,s_im2,r_re2,r_im2,r_re02,r_im02,r_re0_d,r_im0_d,r_re0_u,r_im0_u,eNB2UE,UE2eNB,enb_data,ue_data,abstraction_flag,frame_parms,sf<<1);

    if(Channel_Flag==0)
#endif
      { // SUBFRAME INNER PART
#if defined(ENABLE_ITTI)
        log_set_instance_type (LOG_INSTANCE_ENB);
#endif

	clear_eNB_transport_info (oai_emulation.info.nb_enb_local);

        int all_done=0;
        while (all_done==0) {
          int i;
          all_done = 1;
          for (i = oai_emulation.info.first_enb_local;
               i < oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local;
               i++)
            for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
              if (last_eNB_rx_timestamp[i][CC_id] != current_eNB_rx_timestamp[i][CC_id]) {
                all_done = 0;
                break;
              }
          if (all_done == 1)
            for (i = 0; i < NB_UE_INST; i++)
              for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
                if (last_UE_rx_timestamp[i][CC_id] != current_UE_rx_timestamp[i][CC_id]) {
                  all_done = 0;
                  break;
                }
          if (all_done == 0)
	    usleep(500);
        }

        // increment timestamps
        for (eNB_inst = oai_emulation.info.first_enb_local;
             (eNB_inst
              < (oai_emulation.info.first_enb_local
                 + oai_emulation.info.nb_enb_local));
             eNB_inst++) {
          for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
            current_eNB_rx_timestamp[eNB_inst][CC_id] += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti;
        }
        for (UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
          for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
            current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
        }

        for (eNB_inst = oai_emulation.info.first_enb_local;
             (eNB_inst
              < (oai_emulation.info.first_enb_local
                 + oai_emulation.info.nb_enb_local));
             eNB_inst++) {
          if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) {

	    /*
	    LOG_D(EMU,
		  "PHY procedures eNB %d for frame %d, subframe %d TDD %d/%d Nid_cell %d\n",
		  eNB_inst,
		  frame % MAX_FRAME_NUMBER,
		  sf,
		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.frame_type,
		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.tdd_config,
		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.Nid_cell);

	    */
#ifdef OPENAIR2
	    //Application: traffic gen
            update_otg_eNB (eNB_inst, oai_emulation.info.time_ms);

            //IP/OTG to PDCP and PDCP to IP operation
            //        pdcp_run (frame, 1, 0, eNB_inst); //PHY_vars_eNB_g[eNB_id]->Mod_id
#endif

#ifdef PRINT_STATS

            if((sf==9) && frame%10==0)
              if(eNB_avg_thr)
                fprintf(eNB_avg_thr,"%d %d\n",PHY_vars_eNB_g[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx,
                        (PHY_vars_eNB_g[eNB_inst][0]->total_system_throughput)/((PHY_vars_eNB_g[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx+1)*10));

            if (eNB_stats[eNB_inst]) {
              len = dump_eNB_stats(PHY_vars_eNB_g[eNB_inst][0], stats_buffer, 0);
              rewind (eNB_stats[eNB_inst]);
              fwrite (stats_buffer, 1, len, eNB_stats[eNB_inst]);
              fflush(eNB_stats[eNB_inst]);
            }

#ifdef OPENAIR2

            if (eNB_l2_stats) {
              len = dump_eNB_l2_stats (stats_buffer, 0);
              rewind (eNB_l2_stats);
              fwrite (stats_buffer, 1, len, eNB_l2_stats);
              fflush(eNB_l2_stats);
            }

#endif
#endif
          }
        }// eNB_inst loop

        // Call ETHERNET emulation here
        //emu_transport (frame, last_slot, next_slot, direction, oai_emulation.info.frame_type, ethernet_flag);

#if defined(ENABLE_ITTI)
        log_set_instance_type (LOG_INSTANCE_UE);
#endif

	/*
	clear_UE_transport_info (oai_emulation.info.nb_ue_local);
          clear_UE_transport_info (oai_emulation.info.nb_ue_local);

        for (UE_inst = oai_emulation.info.first_ue_local;
             (UE_inst < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local));
             UE_inst++) {
          if (oai_emulation.info.cli_start_ue[UE_inst] != 0) {
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)

#else

            if (frame >= (UE_inst * 20)) // activate UE only after 20*UE_id frames so that different UEs turn on separately
#endif
            {
              LOG_D(EMU,
                    "PHY procedures UE %d for frame %d, slot %d (subframe TX %d, RX %d)\n",
                    UE_inst, frame % MAX_FRAME_NUMBER, slot, next_slot >> 1,
                    last_slot >> 1);

              if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0]
                  != NOT_SYNCHED) {
                if (frame > 0) {
                  PHY_vars_UE_g[UE_inst][0]->frame_rx = frame % MAX_FRAME_NUMBER;
                  PHY_vars_UE_g[UE_inst][0]->slot_rx =  last_slot;
                  PHY_vars_UE_g[UE_inst][0]->slot_tx = next_slot;

                  if (next_slot > 1)
                    PHY_vars_UE_g[UE_inst][0]->frame_tx = frame % MAX_FRAME_NUMBER;
                  else
                    PHY_vars_UE_g[UE_inst][0]->frame_tx = (frame + 1) % MAX_FRAME_NUMBER;
#ifdef OPENAIR2
                  //Application
                  update_otg_UE (UE_inst, oai_emulation.info.time_ms);

                  //Access layer
		  //		  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, ENB_FLAG_NO, NOT_A_RNTI, frame, next_slot>>1, 0);
		  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, 0, ENB_FLAG_NO, NOT_A_RNTI, frame % MAX_FRAME_NUMBER, next_slot);
                  pdcp_run (&ctxt);
#endif

                  for (CC_id = 0; CC_id < MAX_NUM_CCs;
                       CC_id++) {
                    phy_procedures_UE_lte (
                      PHY_vars_UE_g[UE_inst][CC_id],
		      0, abstraction_flag,
                      normal_txrx, no_relay,
                      NULL);
                  }

                  ue_data[UE_inst]->tx_power_dBm =
                    PHY_vars_UE_g[UE_inst][0]->tx_power_dBm;
                }
              } else {
                if (abstraction_flag == 1) {
                  LOG_E(EMU,
                        "sync not supported in abstraction mode (UE%d,mode%d)\n",
                        UE_inst,
                        PHY_vars_UE_g[UE_inst][0]->UE_mode[0]);
                  exit (-1);
                }

                if ((frame > 0)
                    && (last_slot
                        == (LTE_SLOTS_PER_FRAME
                            - 2))) {
                  initial_sync (PHY_vars_UE_g[UE_inst][0],
                                normal_txrx);

                }
              }

#ifdef PRINT_STATS

              if(last_slot==2 && frame%10==0) {
                if (UE_stats_th[UE_inst]) {
                  fprintf(UE_stats_th[UE_inst],"%d %d\n",frame%MAX_FRAME_NUMBER, PHY_vars_UE_g[UE_inst][0]->bitrate[0]/1000);
                }
              }

              if (UE_stats[UE_inst]) {
                len = dump_ue_stats (PHY_vars_UE_g[UE_inst][0], stats_buffer, 0, normal_txrx, 0);
                rewind (UE_stats[UE_inst]);
                fwrite (stats_buffer, 1, len, UE_stats[UE_inst]);
                fflush(UE_stats[UE_inst]);
              }

#endif
            }
          }
        }

#if defined(Rel10) || defined(Rel14)

        for (RN_id=oai_emulation.info.first_rn_local;
             RN_id<oai_emulation.info.first_rn_local+oai_emulation.info.nb_rn_local;
             RN_id++) {
          // UE id and eNB id of the RN
          UE_inst= oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local + RN_id;// NB_UE_INST + RN_id
          eNB_inst= oai_emulation.info.first_enb_local+oai_emulation.info.nb_enb_local + RN_id;// NB_eNB_INST + RN_id

          // currently only works in FDD
          if (oai_emulation.info.eMBMS_active_state == 4) {
            r_type = multicast_relay;
            //LOG_I(EMU,"Activating the multicast relaying\n");
          } else {
            LOG_E(EMU,"Not supported eMBMS option when relaying is enabled %d\n", r_type);
            exit(-1);
          }

          PHY_vars_RN_g[RN_id]->frame = frame % MAX_FRAME_NUMBER;

          if ( oai_emulation.info.frame_type == 0) {
            // RN == UE
            if (frame>0) {
              if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0] != NOT_SYNCHED) {
                LOG_D(EMU,"[RN %d] PHY procedures UE %d for frame %d, slot %d (subframe TX %d, RX %d)\n",
                      RN_id, UE_inst, frame, slot, next_slot >> 1,last_slot>>1);
                PHY_vars_UE_g[UE_inst][0]->frame_rx = frame % MAX_FRAME_NUMBER;
                PHY_vars_UE_g[UE_inst][0]->slot_rx = last_slot;
                PHY_vars_UE_g[UE_inst][0]->slot_tx = next_slot;

                if (next_slot>1) PHY_vars_UE_g[UE_inst][0]->frame_tx = frame % MAX_FRAME_NUMBER;
                else PHY_vars_UE_g[UE_inst][0]->frame_tx = (frame+1) % MAX_FRAME_NUMBER;

                phy_procedures_UE_lte (PHY_vars_UE_g[UE_inst][0], 0, abstraction_flag,normal_txrx,
                                       r_type, PHY_vars_RN_g[RN_id]);
              } else if (last_slot == (LTE_SLOTS_PER_FRAME-2)) {
                initial_sync(PHY_vars_UE_g[UE_inst][0],normal_txrx);
              }
            }

        emu_transport (frame % MAX_FRAME_NUMBER, sf<<1, ((sf+4)%10)<<1, subframe_select(&PHY_vars_eNB_g[0][0]->frame_parms,sf),
                       oai_emulation.info.frame_type[0], ethernet_flag);

	start_meas (&dl_chan_stats);

	for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++)
	  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
	    //#warning figure out what to do with UE frame_parms during initial_sync
	    do_DL_sig (r_re0,
		       r_im0,
		       r_re,
		       r_im,
		       s_re,
		       s_im,
		       eNB2UE,
		       enb_data,
		       ue_data,
		       PHY_vars_eNB_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1,
		       abstraction_flag,
		       &PHY_vars_eNB_g[0][CC_id]->frame_parms,
		       UE_inst, CC_id);
	    do_DL_sig (r_re0,
		       r_im0,
		       r_re,
		       r_im,n

		       s_re,
		       s_im,
		       eNB2UE,
		       enb_data,
		       ue_data,
		       (PHY_vars_eNB_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1)+1,
		       abstraction_flag,
		       &PHY_vars_eNB_g[0][CC_id]->frame_parms,
		       UE_inst, CC_id);
	  }

	stop_meas (&dl_chan_stats);

	start_meas (&ul_chan_stats);

	for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
	  //#warning figure out what to do with UE frame_parms during initial_sync
	  do_UL_sig (r_re0, r_im0, r_re, r_im, s_re, s_im, UE2eNB,
		     enb_data, ue_data,
		     PHY_vars_UE_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1,
		     abstraction_flag,
		     &PHY_vars_eNB_g[0][CC_id]->frame_parms,
		     frame % MAX_FRAME_NUMBER, CC_id);
	  do_UL_sig (r_re0, r_im0, r_re, r_im, s_re, s_im, UE2eNB,
		     enb_data, ue_data,
		     (PHY_vars_UE_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1)+1,
		     abstraction_flag,
		     &PHY_vars_eNB_g[0][CC_id]->frame_parms,
		     frame % MAX_FRAME_NUMBER, CC_id);
	}

	stop_meas (&ul_chan_stats);

	*/

	if ((sf == 0) && ((frame % MAX_FRAME_NUMBER) == 0) && (abstraction_flag == 0)
	    && (oai_emulation.info.n_frames == 1)) {

	  write_output ("dlchan0.m",
			"dlch0",
			&(PHY_vars_UE_g[0][0]->common_vars.common_vars_rx_data_per_thread[0].dl_ch_estimates[0][0][0]),
			(6
			 * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
			1, 1);
	  write_output ("dlchan1.m",
			"dlch1",
			&(PHY_vars_UE_g[0][0]->common_vars.common_vars_rx_data_per_thread[0].dl_ch_estimates[1][0][0]),
			(6
			 * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
			1, 1);
	  write_output ("dlchan2.m",
			"dlch2",
			&(PHY_vars_UE_g[0][0]->common_vars.common_vars_rx_data_per_thread[0].dl_ch_estimates[2][0][0]),
			(6
			 * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
			1, 1);
	  write_output ("pbch_rxF_comp0.m",
			"pbch_comp0",
			PHY_vars_UE_g[0][0]->pbch_vars[0]->rxdataF_comp[0],
			6 * 12 * 4, 1, 1);
	  write_output ("pbch_rxF_llr.m", "pbch_llr",
			PHY_vars_UE_g[0][0]->pbch_vars[0]->llr,
			(frame_parms[0]->Ncp == 0) ? 1920 : 1728, 1,
			4);
	}

	stop_meas (&oaisim_stats_f);
      } // SUBFRAME INNER PART

    }
    /*
    if ((frame >= 10) && (frame <= 11) && (abstraction_flag == 0)
#ifdef PROC
	&&(Channel_Flag==0)
#endif
	) {
      sprintf (fname, "UEtxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_UE_g[0][0]->common_vars.txdata[0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
      sprintf (fname, "eNBtxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_eNB_g[0][0]->common_vars.txdata[0][0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
      sprintf (fname, "eNBtxsigF%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "txsF%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_eNB_g[0][0]->common_vars.txdataF[0][0],
		    PHY_vars_eNB_g[0][0]->frame_parms.symbols_per_tti
		    * PHY_vars_eNB_g[0][0]->frame_parms.ofdm_symbol_size,
		    1, 1);
      sprintf (fname, "UErxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_UE_g[0][0]->common_vars.rxdata[0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
      sprintf (fname, "eNBrxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_eNB_g[0][0]->common_vars.rxdata[0][0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
    }
    */

    //#ifdef XFORMS
    if (xforms==1) {
      eNB_inst = 0;

      for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) {
	for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
	  phy_scope_UE(form_ue[CC_id][UE_inst],
		   PHY_vars_UE_g[UE_inst][CC_id],
		   eNB_inst,
		   UE_inst,
		   7);
	}

	phy_scope_eNB(form_enb[UE_inst],
		      PHY_vars_eNB_g[eNB_inst][0],
		      UE_inst);

      }
    }
    //#endif

#ifdef SMBV

    // Rohde&Schwarz SMBV100A vector signal generator
    if ((frame % MAX_FRAME_NUMBER == config_frames[0]) || (frame % MAX_FRAME_NUMBER == config_frames[1]) || (frame % MAX_FRAME_NUMBER == config_frames[2]) || (frame % MAX_FRAME_NUMBER == config_frames[3])) {
      smbv_frame_cnt++;
    }

#endif

  } // frame loop

  stop_meas (&oaisim_stats);
  oai_shutdown ();

#ifdef PRINT_STATS

  for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
    if (UE_stats[UE_inst])
      fclose (UE_stats[UE_inst]);

    if(UE_stats_th[UE_inst])
      fclose (UE_stats_th[UE_inst]);
  }

  for (eNB_inst=0; eNB_inst<NB_eNB_INST; eNB_inst++) {
    if (eNB_stats[eNB_inst])
      fclose (eNB_stats[eNB_inst]);
  }

  if (eNB_avg_thr)
    fclose (eNB_avg_thr);

  if (eNB_l2_stats)
    fclose (eNB_l2_stats);

#endif

#if defined(ENABLE_ITTI)
  itti_terminate_tasks(TASK_L2L1);
#endif

  return NULL;
}

#if defined(FLEXRAN_AGENT_SB_IF)
/*
 * The following two functions are meant to restart *the lte-softmodem* and are
 * here to make oaisim compile. A restart command from the controller will be
 * ignored in oaisim.
 */
int stop_L1L2(int enb_id)
{
  LOG_W(FLEXRAN_AGENT, "stop_L1L2() not supported in oaisim\n");
  return 0;
}

int restart_L1L2(int enb_id)
{
  LOG_W(FLEXRAN_AGENT, "restart_L1L2() not supported in oaisim\n");
  return 0;
}
#endif

#if T_TRACER
int T_wait = 1;       /* by default we wait for the tracer */
int T_port = 2021;    /* default port to listen to to wait for the tracer */
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
#endif

static void print_current_directory(void)
{
  char dir[8192]; /* arbitrary size (should be big enough) */
  if (getcwd(dir, 8192) == NULL)
    printf("ERROR getting working directory\n");
  else
    printf("working directory: %s\n", dir);
}

/*------------------------------------------------------------------------------*/
int
main (int argc, char **argv)
{

  clock_t t;

  print_current_directory();

  start_background_system();

#ifdef SMBV
  // Rohde&Schwarz SMBV100A vector signal generator
  strcpy(smbv_ip,DEFAULT_SMBV_IP);
#endif

#ifdef PROC
  int node_id;
  int port,Process_Flag=0,wgt,Channel_Flag=0,temp;
#endif

  //default parameters
  oai_emulation.info.n_frames = MAX_FRAME_NUMBER; //1024;          //10;
  oai_emulation.info.n_frames_flag = 0; //fixme
  snr_dB = 30;

  //Default values if not changed by the user in get_simulation_options();
  pdcp_period = 1;
  omg_period = 1;
  //Clean ip rule table
  for(int i =0; i<NUMBER_OF_UE_MAX; i++){
      char command_line[100];
      sprintf(command_line, "while ip rule del table %d; do true; done",i+201);
      /* we don't care about return value from system(), but let's the
       * compiler be silent, so let's do "if (XX);"
       */
      if (system(command_line)) /* nothing */;
  }
  // start thread for log gen
  log_thread_init ();

  init_oai_emulation (); // to initialize everything !!!

  // get command-line options
  get_simulation_options (argc, argv); //Command-line options

#if T_TRACER
  T_init(T_port, T_wait, T_dont_fork);
#endif

  // Initialize VCD LOG module
  VCD_SIGNAL_DUMPER_INIT (oai_emulation.info.vcd_file);

#if !defined(ENABLE_ITTI)
  pthread_t tid;
  int err;
  sigset_t sigblock;
  sigemptyset (&sigblock);
  sigaddset (&sigblock, SIGHUP);
  sigaddset (&sigblock, SIGINT);
  sigaddset (&sigblock, SIGTERM);
  sigaddset (&sigblock, SIGQUIT);
  //sigaddset(&sigblock, SIGKILL);

  if ((err = pthread_sigmask (SIG_BLOCK, &sigblock, NULL)) != 0) {
    printf ("SIG_BLOCK error\n");
    return -1;
  }

  if (pthread_create (&tid, NULL, sigh, NULL)) {
    printf ("Pthread for tracing Signals is not created!\n");
    return -1;
  } else {
    printf ("Pthread for tracing Signals is created!\n");
  }

#endif
  // configure oaisim with OCG
  oaisim_config (); // config OMG and OCG, OPT, OTG, OLG

  if (ue_connection_test == 1) {
    snr_direction = -snr_step;
    snr_dB = 20;
    sinr_dB = -20;
  }

  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
  pthread_mutex_init(&subframe_mutex, NULL);

#ifdef OPENAIR2
  init_omv ();
#endif
  //Before this call, NB_UE_INST and NB_eNB_INST are not set correctly
  check_and_adjust_params ();

  set_seed = oai_emulation.emulation_config.seed.value;

  init_otg_pdcp_buffer ();

  init_seed (set_seed);

  init_openair1 ();

  init_openair2 ();

  void init_openair0(void);
  init_openair0();

  init_ocm ();

#if defined(ENABLE_ITTI)
  // Note: Cannot handle both RRU/RAU and eNB at the same time, if the first "eNB" is an RRU/RAU, no NAS
  if (oai_emulation.info.node_function[0] < NGFI_RAU_IF4p5) {
    if (create_tasks(oai_emulation.info.nb_enb_local,
		     oai_emulation.info.nb_ue_local) < 0)
      exit(-1); // need a softer mode
  }
  else {
    if (create_tasks(0,
		     oai_emulation.info.nb_ue_local) < 0)
      exit(-1); // need a softer mode
  }
#endif

  // wait for all threads to startup
  sleep(3);
  printf("Sending sync to all threads\n");

  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);

#ifdef SMBV
  // Rohde&Schwarz SMBV100A vector signal generator
  smbv_init_config(smbv_fname, smbv_nframes);
  smbv_write_config_from_frame_parms(smbv_fname, &PHY_vars_eNB_g[0][0]->frame_parms);
#endif

  /* #if defined (FLEXRAN_AGENT_SB_IF)
  flexran_agent_start();
  #endif */

  // add events to future event list: Currently not used
  //oai_emulation.info.oeh_enabled = 1;
  if (oai_emulation.info.oeh_enabled == 1)
    schedule_events ();

  // oai performance profiler is enabled
  if (oai_emulation.info.opp_enabled == 1)
    reset_opp_meas_oaisim ();

  cpuf=get_cpu_freq_GHz();

  init_time ();

  init_slot_isr ();

  t = clock ();

  LOG_N(EMU,
        ">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU initialization done <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");

#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(EMU, "Version: %s\n", PACKAGE_VERSION);

#if defined(ENABLE_ITTI)

  // Handle signals until all tasks are terminated
  itti_wait_tasks_end();

#else

  if (oai_emulation.info.nb_enb_local > 0) {
    eNB_app_task (NULL); // do nothing for the moment
  }

  l2l1_task (NULL);
#endif
  t = clock () - t;
  LOG_I(EMU, "Duration of the simulation: %f seconds\n",
        ((float) t) / CLOCKS_PER_SEC);

  LOG_N(EMU,
        ">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU Ending <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");

  raise (SIGINT);
  //  oai_shutdown ();

  return (0);
}

void
reset_opp_meas_oaisim (void)
{
  uint8_t eNB_id = 0, UE_id = 0;

  reset_meas (&oaisim_stats);
  reset_meas (&oaisim_stats_f); // frame

  // init time stats here (including channel)
  reset_meas (&dl_chan_stats);
  reset_meas (&ul_chan_stats);

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[0]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[1]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[0]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[1]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_tx);

    reset_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_channel_estimation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_freq_offset_estimation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[0]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[1]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_turbo_decoding_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_llr_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_unscrambling_stats);

    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_init_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_alpha_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_beta_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_gamma_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_ext_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl1_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl2_stats);

    reset_meas (&PHY_vars_UE_g[UE_id][0]->tx_prach);

    reset_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_mod_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_encoding_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_modulation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_segmentation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_rate_matching_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_turbo_encoding_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_interleaving_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_multiplexing_stats);
    /*
     * L2 functions
     */

    // UE MAC
    reset_meas (&UE_mac_inst[UE_id].ue_scheduler); // total
    reset_meas (&UE_mac_inst[UE_id].tx_ulsch_sdu); // inlcude rlc_data_req + mac header gen
    reset_meas (&UE_mac_inst[UE_id].rx_dlsch_sdu); // include mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind and  mac header parser
    reset_meas (&UE_mac_inst[UE_id].ue_query_mch);
    reset_meas (&UE_mac_inst[UE_id].rx_mch_sdu); // include rld_data_ind+ parse mch header
    reset_meas (&UE_mac_inst[UE_id].rx_si); // include rlc_data_ind + mac header parser

    reset_meas (&UE_pdcp_stats[UE_id].pdcp_run);
    reset_meas (&UE_pdcp_stats[UE_id].data_req);
    reset_meas (&UE_pdcp_stats[UE_id].data_ind);
    reset_meas (&UE_pdcp_stats[UE_id].apply_security);
    reset_meas (&UE_pdcp_stats[UE_id].validate_security);
    reset_meas (&UE_pdcp_stats[UE_id].pdcp_ip);
    reset_meas (&UE_pdcp_stats[UE_id].ip_pdcp);

  }

  for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {

    for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
      reset_meas (&eNB2UE[eNB_id][UE_id][0]->random_channel);
      reset_meas (&eNB2UE[eNB_id][UE_id][0]->interp_time);
      reset_meas (&eNB2UE[eNB_id][UE_id][0]->interp_freq);
      reset_meas (&eNB2UE[eNB_id][UE_id][0]->convolution);
      reset_meas (&UE2eNB[UE_id][eNB_id][0]->random_channel);
      reset_meas (&UE2eNB[UE_id][eNB_id][0]->interp_time);
      reset_meas (&UE2eNB[UE_id][eNB_id][0]->interp_freq);
      reset_meas (&UE2eNB[UE_id][eNB_id][0]->convolution);
    }

    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_rx);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_tx);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->rx_prach);

    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_mod_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_encoding_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_modulation_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_scrambling_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_rate_matching_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_turbo_encoding_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_interleaving_stats);

    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_demod_stats);
    //reset_meas(&PHY_vars_eNB_g[eNB_id]->rx_dft_stats);
    //reset_meas(&PHY_vars_eNB_g[eNB_id]->ulsch_channel_estimation_stats);
    //reset_meas(&PHY_vars_eNB_g[eNB_id]->ulsch_freq_offset_estimation_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_decoding_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demodulation_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_rate_unmatching_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_turbo_decoding_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_deinterleaving_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demultiplexing_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_llr_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_init_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_alpha_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_beta_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_gamma_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_ext_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl1_stats);
    reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl2_stats);
#ifdef LOCALIZATION
    reset_meas(&PHY_vars_eNB_g[eNB_id][0]->localization_stats);
#endif

    /*
     * L2 functions
     */
    // eNB MAC
    reset_meas (&eNB_mac_inst[eNB_id].eNB_scheduler); // total
    reset_meas (&eNB_mac_inst[eNB_id].schedule_si); // only schedule + tx
    reset_meas (&eNB_mac_inst[eNB_id].schedule_ra); // only ra
    reset_meas (&eNB_mac_inst[eNB_id].schedule_ulsch); // onlu ulsch
    reset_meas (&eNB_mac_inst[eNB_id].fill_DLSCH_dci); // only dci
    reset_meas (&eNB_mac_inst[eNB_id].schedule_dlsch_preprocessor); // include rlc_data_req + MAC header gen
    reset_meas (&eNB_mac_inst[eNB_id].schedule_dlsch); // include rlc_data_req + MAC header gen + pre-processor
    reset_meas (&eNB_mac_inst[eNB_id].schedule_mch); // only embms
    reset_meas (&eNB_mac_inst[eNB_id].rx_ulsch_sdu); // include rlc_data_ind + mac header parser

    reset_meas (&eNB_pdcp_stats[eNB_id].pdcp_run);
    reset_meas (&eNB_pdcp_stats[eNB_id].data_req);
    reset_meas (&eNB_pdcp_stats[eNB_id].data_ind);
    reset_meas (&eNB_pdcp_stats[eNB_id].apply_security);
    reset_meas (&eNB_pdcp_stats[eNB_id].validate_security);
    reset_meas (&eNB_pdcp_stats[eNB_id].pdcp_ip);
    reset_meas (&eNB_pdcp_stats[eNB_id].ip_pdcp);

  }
}

void
print_opp_meas_oaisim (void)
{

  uint8_t eNB_id = 0, UE_id = 0;

  print_meas (&oaisim_stats, "[OAI][total_exec_time]", &oaisim_stats,
              &oaisim_stats);
  print_meas (&oaisim_stats_f, "[OAI][SF_exec_time]", &oaisim_stats,
              &oaisim_stats_f);

  print_meas (&dl_chan_stats, "[DL][chan_stats]", &oaisim_stats,
              &oaisim_stats_f);
  print_meas (&ul_chan_stats, "[UL][chan_stats]", &oaisim_stats,
              &oaisim_stats_f);

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
    for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
      print_meas (&eNB2UE[eNB_id][UE_id][0]->random_channel,
                  "[DL][random_channel]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&eNB2UE[eNB_id][UE_id][0]->interp_time,
                  "[DL][interp_time]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&eNB2UE[eNB_id][UE_id][0]->interp_freq,
                  "[DL][interp_freq]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&eNB2UE[eNB_id][UE_id][0]->convolution,
                  "[DL][convolution]", &oaisim_stats, &oaisim_stats_f);

      print_meas (&UE2eNB[UE_id][eNB_id][0]->random_channel,
                  "[UL][random_channel]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&UE2eNB[UE_id][eNB_id][0]->interp_time,
                  "[UL][interp_time]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&UE2eNB[UE_id][eNB_id][0]->interp_freq,
                  "[UL][interp_freq]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&UE2eNB[UE_id][eNB_id][0]->convolution,
                  "[UL][convolution]", &oaisim_stats, &oaisim_stats_f);
    }
  }

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[0], "[UE][total_phy_proc[0]]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[1], "[UE][total_phy_proc[1]]",
                &oaisim_stats, &oaisim_stats_f);

    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[0],
                "[UE][total_phy_proc_rx[0]]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[1],
                "[UE][total_phy_proc_rx[1]]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats,
                "[UE][ofdm_demod]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats, "[UE][rx_dft]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_channel_estimation_stats,
                "[UE][channel_est]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_freq_offset_estimation_stats,
                "[UE][freq_offset]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_llr_stats, "[UE][llr]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_unscrambling_stats,
                "[UE][unscrambling]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[0],
                "[UE][decoding[0]]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[1],
                "[UE][decoding[1]]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats,
                "[UE][rate_unmatching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats,
                "[UE][deinterleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_turbo_decoding_stats,
                "[UE][turbo_decoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_init_stats,
                "[UE][ |_tc_init]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_alpha_stats,
                "[UE][ |_tc_alpha]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_beta_stats,
                "[UE][ |_tc_beta]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_gamma_stats,
                "[UE][ |_tc_gamma]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_ext_stats,
                "[UE][ |_tc_ext]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl1_stats,
                "[UE][ |_tc_intl1]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl2_stats,
                "[UE][ |_tc_intl2]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_tx,
                "[UE][total_phy_proc_tx]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_mod_stats, "[UE][ofdm_mod]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_modulation_stats,
                "[UE][modulation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_encoding_stats,
                "[UE][encoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_segmentation_stats,
                "[UE][segmentation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_rate_matching_stats,
                "[UE][rate_matching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_turbo_encoding_stats,
                "[UE][turbo_encoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_interleaving_stats,
                "[UE][interleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_multiplexing_stats,
                "[UE][multiplexing]", &oaisim_stats, &oaisim_stats_f);

  }

  for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc,
                "[eNB][total_phy_proc]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_tx,
                "[eNB][total_phy_proc_tx]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_mod_stats,
                "[eNB][ofdm_mod]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_modulation_stats,
                "[eNB][modulation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_scrambling_stats,
                "[eNB][scrambling]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_encoding_stats,
                "[eNB][encoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_interleaving_stats,
                "[eNB][|_interleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_rate_matching_stats,
                "[eNB][|_rate_matching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_turbo_encoding_stats,
                "[eNB][|_turbo_encoding]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_rx,
                "[eNB][total_phy_proc_rx]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_demod_stats,
                "[eNB][ofdm_demod]", &oaisim_stats, &oaisim_stats_f);
    //print_meas(&PHY_vars_eNB_g[eNB_id][0]->ulsch_channel_estimation_stats,"[eNB][channel_est]");
    //print_meas(&PHY_vars_eNB_g[eNB_id][0]->ulsch_freq_offset_estimation_stats,"[eNB][freq_offset]");
    //print_meas(&PHY_vars_eNB_g[eNB_id][0]->rx_dft_stats,"[eNB][rx_dft]");
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demodulation_stats,
                "[eNB][demodulation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_decoding_stats,
                "[eNB][decoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_deinterleaving_stats,
                "[eNB][|_deinterleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demultiplexing_stats,
                "[eNB][|_demultiplexing]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_rate_unmatching_stats,
                "[eNB][|_rate_unmatching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_turbo_decoding_stats,
                "[eNB][|_turbo_decoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_init_stats,
                "[eNB][ |_tc_init]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_alpha_stats,
                "[eNB][ |_tc_alpha]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_beta_stats,
                "[eNB][ |_tc_beta]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_gamma_stats,
                "[eNB][ |_tc_gamma]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_ext_stats,
                "[eNB][ |_tc_ext]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl1_stats,
                "[eNB][ |_tc_intl1]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl2_stats,
                "[eNB][ |_tc_intl2]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&PHY_vars_eNB_g[eNB_id][0]->rx_prach, "[eNB][rx_prach]",
                &oaisim_stats, &oaisim_stats_f);

#ifdef LOCALIZATION
    print_meas(&PHY_vars_eNB_g[eNB_id][0]->localization_stats, "[eNB][LOCALIZATION]",&oaisim_stats,&oaisim_stats_f);
#endif
  }

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {

    print_meas (&UE_mac_inst[UE_id].ue_scheduler, "[UE][mac_scheduler]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].tx_ulsch_sdu, "[UE][tx_ulsch_sdu]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].rx_dlsch_sdu, "[UE][rx_dlsch_sdu]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].ue_query_mch, "[UE][query_MCH]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].rx_mch_sdu, "[UE][rx_mch_sdu]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].rx_si, "[UE][rx_si]", &oaisim_stats,
                &oaisim_stats_f);

    print_meas (&UE_pdcp_stats[UE_id].pdcp_run, "[UE][total_pdcp_run]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].data_req, "[UE][DL][pdcp_data_req]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].data_ind, "[UE][UL][pdcp_data_ind]",
                &oaisim_stats, &oaisim_stats_f);

    print_meas (&UE_pdcp_stats[UE_id].apply_security,
                "[UE][DL][apply_security]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].validate_security,
                "[UE][UL][validate_security]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].ip_pdcp, "[UE][DL][ip_pdcp]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].pdcp_ip, "[UE][UL][pdcp_ip]",
                &oaisim_stats, &oaisim_stats_f);

  }

  for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {

    print_meas (&eNB_mac_inst[eNB_id].eNB_scheduler, "[eNB][mac_scheduler]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].schedule_si, "[eNB][DL][SI]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].schedule_ra, "[eNB][DL][RA]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].fill_DLSCH_dci,
                "[eNB][DL/UL][fill_DCI]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].schedule_dlsch_preprocessor,
                "[eNB][DL][preprocessor]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].schedule_dlsch,
                "[eNB][DL][schedule_tx_dlsch]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].schedule_mch, "[eNB][DL][mch]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].schedule_ulsch, "[eNB][UL][ULSCH]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_mac_inst[eNB_id].rx_ulsch_sdu,
                "[eNB][UL][rx_ulsch_sdu]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&eNB_pdcp_stats[eNB_id].pdcp_run, "[eNB][pdcp_run]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].data_req,
                "[eNB][DL][pdcp_data_req]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].data_ind,
                "[eNB][UL][pdcp_data_ind]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&eNB_pdcp_stats[eNB_id].apply_security,
                "[eNB][DL][apply_security]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].validate_security,
                "[eNB][UL][validate_security]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].ip_pdcp, "[eNB][DL][ip_pdcp]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].pdcp_ip, "[eNB][UL][pdcp_ip]",
                &oaisim_stats, &oaisim_stats_f);

  }

}

#if !defined(ENABLE_ITTI)
static void *
sigh (void *arg)
{

  int signum;
  sigset_t sigcatch;
  sigemptyset (&sigcatch);
  sigaddset (&sigcatch, SIGHUP);
  sigaddset (&sigcatch, SIGINT);
  sigaddset (&sigcatch, SIGTERM);
  sigaddset (&sigcatch, SIGQUIT);

  for (;;) {
    sigwait (&sigcatch, &signum);

    //sigwait(&sigblock, &signum);
    switch (signum) {
    case SIGHUP:
    case SIGINT:
    case SIGTERM:
    case SIGQUIT:
      fprintf (stderr, "received signal %d \n", signum);
      // no need for mutx: when ITTI not used, this variable is only accessed by this function
      l2l1_state = L2L1_TERMINATED;
      break;

    default:
      fprintf (stderr, "Unexpected signal %d \n", signum);
      exit (-1);
      break;
    }
  }

  pthread_exit (NULL);
}
#endif /* !defined(ENABLE_ITTI) */

void
oai_shutdown (void)
{
  static int done = 0;

  if (done)
    return;

  free (otg_pdcp_buffer);
  otg_pdcp_buffer = 0;

#ifdef SMBV

  // Rohde&Schwarz SMBV100A vector signal generator
  if (config_smbv) {
    smbv_send_config (smbv_fname,smbv_ip);
  }

#endif

  //Perform KPI measurements
  if (oai_emulation.info.otg_enabled == 1){
    LOG_N(EMU,"calling OTG kpi gen .... \n");
    kpi_gen ();
  }
  if (oai_emulation.info.opp_enabled == 1)
    print_opp_meas_oaisim ();

  // relase all rx state
  if (ethernet_flag == 1) {
    emu_transport_release ();
  }

#ifdef PROC

  if (abstraction_flag == 0 && Channel_Flag==0 && Process_Flag==0)
#else
    if (abstraction_flag == 0)
#endif
      {
	/*
	  #ifdef IFFT_FPGA
	  free(txdataF2[0]);
	  free(txdataF2[1]);
	  free(txdataF2);
	  free(txdata[0]);
	  free(txdata[1]);
	  free(txdata);
	  #endif
	*/
	/*
	for (int i = 0; i < 2; i++) {
	  free (s_re[i]);
	  free (s_im[i]);
	  free (r_re[i]);
	  free (r_im[i]);
	}

	free (s_re);
	free (s_im);
	free (r_re);
	free (r_im);
	s_re = 0;
	s_im = 0;
	r_re = 0;
	r_im = 0;*/

	lte_sync_time_free ();
      }

  // added for PHY abstraction
  if (oai_emulation.info.ocm_enabled == 1) {
    for (eNB_inst = 0; eNB_inst < NUMBER_OF_eNB_MAX; eNB_inst++) {
      free (enb_data[eNB_inst]);
      enb_data[eNB_inst] = 0;
    }

    for (UE_inst = 0; UE_inst < NUMBER_OF_UE_MAX; UE_inst++) {
      free (ue_data[UE_inst]);
      ue_data[UE_inst] = 0;
    }
  } //End of PHY abstraction changes

#ifdef OPENAIR2
  mac_top_cleanup ();
#endif

  // stop OMG
  stop_mobility_generator (omg_param_list); //omg_param_list.mobility_type
#ifdef OPENAIR2

  if (oai_emulation.info.omv_enabled == 1)
    omv_end (pfd[1], omv_data);

#endif

  if ((oai_emulation.info.ocm_enabled == 1) && (ethernet_flag == 0)
      && (ShaF != NULL)) {
    destroyMat (ShaF, map1, map2);
    ShaF = 0;
  }

  if (opt_enabled == 1)
    terminate_opt ();

  if (oai_emulation.info.cli_enabled)
    cli_server_cleanup ();

  for (int i = 0; i < NUMBER_OF_eNB_MAX + NUMBER_OF_UE_MAX; i++)
    if (oai_emulation.info.oai_ifup[i] == 1) {
      char interfaceName[8];
      snprintf (interfaceName, sizeof(interfaceName), "oai%d", i);
      bringInterfaceUp (interfaceName, 0);
    }

  log_thread_finalize ();
  logClean ();
  VCD_SIGNAL_DUMPER_CLOSE ();

  done = 1; // prevent next invokation of this function

  LOG_N(EMU,
        ">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU shutdown <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
}

eNB_MAC_INST*
get_eNB_mac_inst (module_id_t module_idP)
{
  return (&eNB_mac_inst[module_idP]);
}

OAI_Emulation*
get_OAI_emulation ()
{
  return &oai_emulation;
}