Modelica(Dymola)中一维热扩散PDE的实现

Modelica(Dymola)中一维热扩散PDE的实现,modelica,pde,dymola,Modelica,Pde,Dymola,我试图实现Peter Fritzon的“Modelica 3.3面向对象建模与仿真”中的一维热扩散示例,该示例基于一维热扩散的网格函数有限差分方法,但我得到了一个错误: Translation of Heat_diffusion_Test_1D.HeatDiffusion1D: The DAE has 50 scalar unknowns and 50 scalar equations. Cannot find differentiation function: Heat_diffusion

我试图实现Peter Fritzon的“Modelica 3.3面向对象建模与仿真”中的一维热扩散示例,该示例基于一维热扩散的网格函数有限差分方法,但我得到了一个错误:

Translation of Heat_diffusion_Test_1D.HeatDiffusion1D:

The DAE has 50 scalar unknowns and 50 scalar equations.

Cannot find differentiation function:
Heat_diffusion_Test_1D.DifferentialOperators1D.pder(
u, 
1)
with respect to time

    Failed to differentiate the equation
    Heat_diffusion_Test_1D.FieldDomainOperators1D.right(Heat_diffusion_Test_1D.DifferentialOperators1D.pder (
    u, 
    1)) = 0;

    in order to reduce the DAE index.

    Failed to reduce the DAE index.

    Translation aborted.

    ERROR: 1 error was found

    WARNING: 1 warning was issued
我是编程语言的新用户,你知道我如何解决这个问题吗?显然,问题在于右边界的边界条件。 提前谢谢你

代码如下:

package Heat_diffusion_Test_1D
import SI = Modelica.SIunits;
  model HeatDiffusion1D
    import SI = Modelica.SIunits;
    parameter SI.Length L=1;
    import Heat_diffusion_Test_1D.Fields.*;
    import Heat_diffusion_Test_1D.Domains.*;
    import Heat_diffusion_Test_1D.FieldDomainOperators1D.*;
    import Heat_diffusion_Test_1D.DifferentialOperators1D.*;
    constant Real PI=Modelica.Constants.pi;

    Domain1D rod(left=0, right=L, n=50);
    Field1D u(domain=rod, redeclare type FieldValueType=SI.Temperature, start={20*sin(PI/2*x)+ 300 for x in rod.x});

  equation 
    interior(der(u.val))=interior(4*pder(u,x=2));
    left(u.val)=20*sin(PI/12*time)+300;
   right(pder(u,x=1)) = 0;
    //right(u.val)=320;

    annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
          coordinateSystem(preserveAspectRatio=false)));
  end HeatDiffusion1D;

  package Fields

    record Field1D "Field over a 1D spatial domain"
      replaceable type FieldValueType = Real;
      parameter Domains.Domain1D domain;
      parameter FieldValueType start[domain.n]=zeros(domain.n);
      FieldValueType val[domain.n](start=start);

      annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
            coordinateSystem(preserveAspectRatio=false)));
    end Field1D;
    annotation ();
  end Fields;

  package Domains
    import SI = Modelica.SIunits;
    record Domain1D "1D spatial domain"
      parameter SI.Length left=0.0;
      parameter SI.Length right=1.0;
      parameter Integer n=100;
      parameter SI.Length dx = (right-left)/(n-1);
      parameter SI.Length x[n]=linspace(right,left,n);

      annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
            coordinateSystem(preserveAspectRatio=false)));
    end Domain1D;
    annotation ();
  end Domains;

  package FieldDomainOperators1D 
    "Selection operators of field on 1D domain"

    function left "Returns the left value of the field vector v1"
      input Real[:] v1;
      output Real v2;

    algorithm 
      v2 := v1[1];
    end left;

    function right "Returns the left value of the field vector v1"
      input Real[:] v1;
      output Real v2;

    algorithm 
      v2 := v1[end];

    end right;

    function interior 
      "returns the interior values of the field as a vector"
      input Real v1[:];
      output Real v2[size(v1,1)-2]; 

    algorithm 
      v2:= v1[2:end-1];

    end interior;


  end FieldDomainOperators1D;

  package DifferentialOperators1D 
    "Finite difference differential operators"

    function pder 
      "returns vector of spatial derivative values of a 1D field"
      input Heat_diffusion_Test_1D.Fields.Field1D f;
      input Integer x=1 "Diff order - first or second order derivative";
      output Real df[size(f.val,1)];

    algorithm 
      df:= if x == 1 then SecondOrder.diff1(f.val, f.domain.dx)
     else 
         SecondOrder.diff2(f.val, f.domain.dx);

    end pder;

    package SecondOrder 
      "Second order polynomial derivative approximations"

      function diff1 "First derivative"
        input Real u[:];
        input Real dx;
        output Real du[size(u,1)];

      algorithm 
        du := cat( 1, {(-3*u[1] + 4*u[2] - u[3])/2/dx},  (u[3:end] - u[1:end-2])/2/dx, {(3*u[end] -4*u[end-1] + u[end-2])/2/dx});

      end diff1;

      function diff2
        input Real u[:];
        input Real dx;
        output Real du2[size(u,1)];
      algorithm 
        du2 :=cat( 1, {(2*u[1] - 5*u[2] + 4*u[3]- u[4])/dx/dx}, (u[3:end] - 2*u[2:end-1] + u[1:end-2])/dx/dx, {(2*u[end] -5*u[end-1] + 4*u[end-2] - u[end-3])/dx/dx});
      end diff2;
      annotation ();
    end SecondOrder;

    package FirstOrder 
      "First order polynomial derivative approximations"

      function diff1 "First derivative"
        input Real u[:];
        input Real dx;
        output Real du[size(u,1)];

      algorithm 
                // Left, central and right differences
        du := cat(1, {(u[2] - u[1])/dx}, (u[3:end]-u[1:end-2])/2/dx, {(u[end] - u[end-1])/dx});

      end diff1;
      annotation ();
    end FirstOrder;
    annotation ();
  end DifferentialOperators1D;
  annotation (uses(Modelica(version="3.2.1")));
end Heat_diffusion_Test_1D;

如果您使用
注释(inline=true)
在包
FieldDomainOperators1D
DifferenticationOperators1d
中的所有函数,您的实现将在
Dymola 2015 FD01
中进行翻译和模拟。原因由Peter Fritzson在第406页给出:

[…]注意,
pder()
函数和 网格函数。[…]这使我们有可能向这样一家公司打电话 在通常不允许函数调用的地方使用函数。[……]


我不确定当前版本的modelica标准库中是否定义了
pder
运算符,我也不认为本书所指的3.3库已经发布?@Christoph如果当前版本中没有定义pder,那是对的。我将其定义为代码中的函数。Modelica标准库是3.2.1。Modelica语言规范是3.3,已经在Dymola(2016 FD01)中实现。我不确定我是否正确理解了这个答案。我想知道你是否可以如此幼稚地在你的帖子中添加正确版本的代码?