# 插值¶

## Modelica实现¶

### 函数定义¶

 自变量$$x$$ 因变量$$y$$ $$x_1$$ $$y_1$$ $$x_2$$ $$y_2$$ $$x_3$$ $$y_3$$ ... ... $$x_n$$ $$y_n$$

function InterpolateVector "Interpolate a function defined by a vector"
input Real x         "Independent variable";
input Real ybar[:,2] "Interpolation data";
output Real y        "Dependent variable";
protected
Integer i;
Integer n = size(ybar,1) "Number of interpolation points";
Real p;
algorithm
assert(x>=ybar[1,1], "Independent variable must be greater than "+String(ybar[1,1]));
assert(x<=ybar[n,1], "Independent variable must be less than "+String(ybar[n,1]));
i := 1;
while x>=ybar[i+1,1] loop
i := i + 1;
end while;
p := (x-ybar[i,1])/(ybar[i+1,1]-ybar[i,1]);
y := p*ybar[i+1,2]+(1-p)*ybar[i,2];
end InterpolateVector;


  input Real x         "Independent variable";
input Real ybar[:,2] "Interpolation data";
output Real y        "Dependent variable";


input变量x表示插值函数求解的独立变量值。变量ybar表示插值数据。output变量y表示利用插值函数求得的内插值。函数包含的下一部分内容如下所示：

protected
Integer i;
Integer n = size(ybar,1) "Number of interpolation points";
Real p;


algorithm
assert(x>=ybar[1,1], "Independent variable must be greater than "+String(ybar[1,1]));
assert(x<=ybar[n,1], "Independent variable must be less than "+String(ybar[n,1]));
i := 1;
while x>=ybar[i+1,1] loop
i := i + 1;
end while;
p := (x-ybar[i,1])/(ybar[i+1,1]-ybar[i,1]);
y := p*ybar[i+1,2]+(1-p)*ybar[i,2];


$y = p\ \bar{y}_{i+1,2}+(1-p)\ \bar{y}_{i,2}$

$p = \frac{x-\bar{y}_{i,1}}{\bar{y}_{i+1,1}-\bar{y}_{i,1}]}$

### 测试用例¶

 $$x$$ $$y$$ 0 0 2 0 4 2 6 0 8 0

model IntegrateInterpolatedVector "Exercises the InterpolateVector"
Real x;
Real y;
Real z;
equation
x = time;
y = InterpolateVector(x, [0.0, 0.0; 2.0, 0.0; 4.0, 2.0; 6.0, 0.0; 8.0, 0.0]);
der(z) = y;
annotation (experiment(StopTime=6));
end IntegrateInterpolatedVector;


## 使用ExternalObject类型¶

ExternalObject类型主要是指定未（或不必）通过Modelica源代码体现的信息。这主要用于指定Modelica源代码以外的数据或状态。这些信息可以是插值函数所用的数据，也可以是其他软件的相关状态。

### 测试用例¶

model IntegrateInterpolatedExternalVector
"Exercises the InterpolateExternalVector"
parameter VectorTable vector = VectorTable(ybar=[0.0, 0.0;
2.0, 0.0;
4.0, 2.0;
6.0, 0.0;
8.0, 0.0]);
Real x;
Real y;
Real z;
equation
x = time;
y = InterpolateExternalVector(x, vector);
der(z) = y;
annotation (experiment(StopTime=6));
end IntegrateInterpolatedExternalVector;


### ExternalObject类型定义¶

type VectorTable "A vector table implemented as an ExternalObject"
extends ExternalObject;
function constructor
input Real ybar[:,2];
output VectorTable table;
external "C" table=createVectorTable(ybar, size(ybar,1))
annotation(IncludeDirectory="modelica://ModelicaByExample.Functions.Interpolation/source",
Include="#include \"VectorTable.c\"");
end constructor;

function destructor "Release storage"
input VectorTable table;
external "C" destroyVectorTable(table)
annotation(IncludeDirectory="modelica://ModelicaByExample.Functions.Interpolation/source",
Include="#include \"VectorTable.c\"");
end destructor;
end VectorTable;


#### 析构函数¶

ExternalObject类型不再需要时，将调用destructor函数。这使得Modelica编译器可以清除ExternalObject类型运行所占用的内存。模型内ExternalObject类型的实例化通常会一直持续到仿真结束。但是，在函数定义时，如果ExternalObject类型被声明为protected变量，则可以在单个表达式的求值过程中创建和销毁。出于上述原因，我们必须确保由ExternalObject类型分配的任何内存在仿真结束后都被释放。

#### 外部C代码¶

#ifndef _VECTOR_TABLE_C_
#define _VECTOR_TABLE_C_

#include <stdlib.h>
#include "ModelicaUtilities.h"

/*
Here we define the structure associated
with our ExternalObject type 'VectorTable'
*/
typedef struct {
double *x; /* Independent variable values */
double *y; /* Dependent variable values */
size_t npoints; /* Number of points in this data */
size_t lastIndex; /* Cached value of last index */
} VectorTable;

void *
createVectorTable(double *data, size_t np) {
VectorTable *table = (VectorTable*) malloc(sizeof(VectorTable));
if (table) {
/* Allocate memory for data */
table->x = (double*) malloc(sizeof(double)*np);
if (table->x) {
table->y = (double*) malloc(sizeof(double)*np);
if (table->y) {
/* Copy data into our local array */
size_t i;
for(i=0;i<np;i++) {
table->x[i] = data[2*i];
table->y[i] = data[2*i+1];
}
/* Initialize the rest of the table object */
table->npoints = np;
table->lastIndex = 0;
}
else {
free(table->x);
free(table);
table = NULL;
ModelicaError("Memory allocation error\n");
}
}
else {
free(table);
table = NULL;
ModelicaError("Memory allocation error\n");
}
}
else {
ModelicaError("Memory allocation error\n");
}
return table;
}

void
destroyVectorTable(void *object) {
VectorTable *table = (VectorTable *)object;
if (table==NULL) return;
free(table->x);
free(table->y);
free(table);
}

double
interpolateVectorTable(void *object, double x) {
VectorTable *table = (VectorTable *)object;
size_t i = table->lastIndex;
double p;

ModelicaFormatMessage("Request to compute value of y at %g\n", x);
if (x<table->x[0])
ModelicaFormatError("Requested value of x=%g is below the lower bound of %g\n",
x, table->x[0]);
if (x>table->x[table->npoints-1])
ModelicaFormatError("Requested value of x=%g is above the upper bound of %g\n",
x, table->x[table->npoints-1]);

while(i<table->npoints-1&&x>table->x[i+1]) i++;
while(i>0&&x<table->x[i]) i--;

p = (x-table->x[i])/(table->x[i+1]-table->x[i]);
table->lastIndex = i;
return p*table->y[i+1]+(1-p)*table->y[i];
}

#endif


#### 插值¶

function InterpolateExternalVector
"Interpolate a function defined by a vector using an ExternalObject"
input Real x;
input VectorTable table;
output Real y;
external "C" y = interpolateVectorTable(table, x)
annotation(IncludeDirectory="modelica://ModelicaByExample.Functions.Interpolation/source",
Include="#include \"VectorTable.c\"");
end InterpolateExternalVector;