找回密码
 注册
Simdroid-非首页
楼主: wanglu

[10. Others] 用Forcal设计科学(计算)软件

[复制链接]
发表于 2009-6-19 13:56:13 | 显示全部楼层 来自 江苏常州
牛人啊
回复 不支持

使用道具 举报

 楼主| 发表于 2009-6-24 15:49:04 | 显示全部楼层 来自 山东淄博
Simdroid开发平台
刚刚升级的脚本控件FcScript,由V C++ ATL、Forcal混合编程设计而成。
                   FcScript V1.0 使用说明(含源代码)
    FcScript是由Forcal和MForcal支持的脚本控件(这两个动态库必须在windows搜索路径内,或者在文件夹“c:\FcDll”中),采用双接口、STA单线程套间模型。目前定义了两种接口:VBMForcal接口(用于VBScript脚本,全部使用VARIANT参数)和CMForcal接口(用于Exel、CAD等各种使用COM对象的地方)。
    FcScript可扩展Excel、CAD等程序的功能并大幅提高其数值运算速度。使用VBScript、JScript等脚本感觉太慢时也需要使用FcScript。Forcal一级函数的计算速度约为(C/C++)或FORTRAN速度的50%左右,二级函数的速度稍有降低。
    FcScript为所有宿主程序提供高速的脚本控制和无限的可扩充性。

    详细说明:http://xoomer.virgilio.it/forcal/sysm/forcal8/fcscript.htm
    详细说明:http://blog.csdn.net/forcal/archive/2009/01/12/3760030.aspx ;

    欢迎下载试用。
回复 不支持

使用道具 举报

发表于 2009-6-25 11:59:48 | 显示全部楼层 来自 浙江杭州
22# wanglu

能不能做一下Matlab接口的,扩展程序的功能并大幅提高其数值运算速度?

因为Matlab在数值计算中的广泛应用,以及提高Matlab的代码运算速度始终是新手难以掌握的问题,所以觉得做一个Matlab接口会更有前景。
回复 不支持

使用道具 举报

 楼主| 发表于 2009-6-25 15:58:30 | 显示全部楼层 来自 山东淄博
在Matlab中VBMForcal接口和CMForcal接口都不能用吗?CMForcal接口适用范围比较广的,可以试一下。
Matlab对第三方COM接口有什么特殊要求吗?
回复 不支持

使用道具 举报

 楼主| 发表于 2009-8-6 10:03:58 | 显示全部楼层 来自 山东淄博
目前,正在升级Forcal V9.0,已基本完成,尚有部分Forcal扩展动态库需完善,可下载体验:
http://xoomer.virgilio.it/forcal/xiazai/forcal9/forcal32w.rar
    在该版本中新增Forcal数值计算扩展动态库XSLSF,算法主要选自《C常用算法程序集》第二版,徐士良主编。主要内容包括矩阵运算,矩阵特征值与特征向量的计算,线性代数方程组的求解,非线性方程与方程组的求解,插值与逼近,数值积分,常微分方程组的求解,极值问题的求解,复数、多项式与特殊函数的计算等。这些算法都是行之有效的,基本可以满足解决工程中各种实际问题的需要。
    我在封装托伯利兹矩阵求逆的特兰持方法(btrch)时运行出错,找了半天,发现该算法的最后似乎有问题:
    ... ...
    for (i=0; i<=n-1; i++)    //如果i<=n-1
    for (j=0; j<=n-2; j++)
      { k=(i+1)*n+j+1;        //当i=n-1时,k=n*n+j+1,将越界
        b[k]=b[i*n+j]-c*b[j+1];
        b[k]=b[k]+c[n-j-2]*b[n-i-1];
      }

    ... ...

    我也不确定是该算法的问题,还是Forcal的问题,如果是该算法的问题,将如何改?有《C常用算法程序集》第二版的朋友帮忙看一下。
    XSLSF源程序下载:http://xoomer.virgilio.it/forcal/xiazai/forcal9/xslsf32wcode.rar
回复 不支持

使用道具 举报

 楼主| 发表于 2009-8-7 13:47:45 | 显示全部楼层 来自 山东淄博
封装托伯利兹矩阵求逆的特兰持方法(btrch)时的错误已修正。重新升级了XSLSF库:已完成的算法有矩阵运算,矩阵特征值与特征向量的计算,线性代数方程组的求解,非线性方程与方程组的求解,插值,特殊函数,随机数的产生等,其余算法有望近期完成。
Forcal程序下载:http://xoomer.virgilio.it/forcal/xiazai/forcal9/forcal32w.rar
XSLSF源程序下载:http://xoomer.virgilio.it/forcal/xiazai/forcal9/xslsf32wcode.rar

Forcal新版本主要升级内容:

    软件用户(2009.8.1):

    1.支持中文编程,可以使用中文标识符,如中文函数名、中文变量等。
    2.使用Unicode字符串作为Forcal默认字符串。扩展了字符串中的转义字符。可通过转义字符定义静态空间。
    3.支持静态数组,相关的存取函数是一级函数,具有很高的执行效率。
    4.整数表达式中的整数升级为64位,可进行更大的数的运算。
    5.在整数表达式中增加了位运算函数,位运算函数是一级函数,具有很高的执行效率。
    6.增加、修改、删除了部分一级函数及二级函数。
    7.增加了访问命名空间的函数using。
    8.修改了部分FcData函数,特别增加了标准格式化输出函数printf和printfs。

    编程用户(2009.8.1):

    1.表达式字符串改为wchar_t字符串(Unicode字符串)。Forcal32W.dll的大部分输出函数使用wchar_t字符串,少部分函数仍使用char字符串。
    2.整数表达式中的整数升级为64位。
    3.编译表达式返回的错误代码新增37、38、39。
    4.指针数据保存在整数、实数或复数的前4个字节中。
    5.FcData中real32数据(相当于C中的float数据)保存在整数或实数的前4个字节中。
    6.FcData中使用Unicode字符串作为默认字符串。
    7.强烈建议Forcal扩展动态库中的函数使用命名空间命名方式。
    8.编程用户应编写移植性高的代码,可方便地移植到64位平台。
    9.并行计算设想:在多核计算机中进行并行运算时,可复制Forcal32W.dll为多个副本Forcal32W1.dll、Forcal32W2.dll、... ...,同时加载Forcal32W.dll及各个副本,Forcal32W.dll及各个副本都有自己的地址空间,可独立运行互不影响,这样可实现并行计算。
回复 不支持

使用道具 举报

 楼主| 发表于 2009-9-2 09:02:13 | 显示全部楼层 来自 山东淄博
封装《C常用算法程序集》数值算法的XSLSF库已全部完成,大家多提宝贵意见。 Forcal V9.0中FcData库有较大修改,更好用了,欢迎下载体验。
Forcal程序下载:http://xoomer.virgilio.it/forcal/xiazai/forcal9/forcal32w.rar
包含XSLSF的源程序下载:http://xoomer.virgilio.it/forcal/xiazai/forcal9/forcal9code.rar
回复 不支持

使用道具 举报

发表于 2009-9-2 14:44:49 | 显示全部楼层 来自 上海
封装《C常用算法程序集》数值算法的XSLSF库已全部完成,大家多提宝贵意见。 Forcal V9.0中FcData库有较大修改,更好用了,欢迎下载体验。
Forcal程序下载:http://xoomer.virgilio.it/forcal/xiazai/forcal9/forcal ...
wanglu 发表于 2009-9-2 09:02

封装那个的话,还不如封装BLAS、LAPACK,后者的可靠性、易用性更好,也更易被接受与认可
回复 不支持

使用道具 举报

 楼主| 发表于 2009-9-3 09:11:24 | 显示全部楼层 来自 山东淄博
谢谢pasuka :
    《C常用算法程序集》在国内有一定影响,包含的算法较全,正好手头上有资料和源代码,因此首先封装成XSLSF库。
    要将一个普通的C函数封装成Forcal函数,需要:(1)有函数参数的说明;(2)有函数源代码或者没有源代码但有该函数的静态库Lib。有源代码可使C函数与Forcal函数结合的更好。封装静态库Lib中的函数将多一次函数调用,效率稍低。
    要将一个普通的Fortran函数封装成Forcal函数,参考上面的说明,但我没有合适的Fortran编译器。
    我搜索了一下BLAS和LAPACK,非常好,但没有发现C/C++版本的。希望能得到更多的中文说明资料。
    如果各位有兴趣,自己可封装BLAS和LAPACK或者其他库,自己有价值的库函数可以设计成加密的Forcal扩展动态库,加密方法参考“FORCAL扩展动态库”说明,Forcal V9.0支持软件版权的保护,互惠互利,共同发展。
回复 不支持

使用道具 举报

发表于 2009-9-3 09:53:38 | 显示全部楼层 来自 上海
谢谢pasuka :
    《C常用算法程序集》在国内有一定影响,包含的算法较全,正好手头上有资料和源代码,因此首先封装成XSLSF库。
    要将一个普通的C函数封装成Forcal函数,需要:(1)有函数参数的说明;(2)有 ...
wanglu 发表于 2009-9-3 09:11

fortran编译器的话,推荐Intel的Fortran编译器,做得比较好
Intel的MKL和AMD的ACML都是包含了BLAS和LAPACK的库,可供C/C++、Fortran程序调用,不过中文资料不多,书籍的话,参考袁亚湘翻译戈卢布的《矩阵计算》,科学出版社
会C++的话,可以考虑用cvmlib,比clapack更容易上手
回复 不支持

使用道具 举报

 楼主| 发表于 2009-9-5 07:16:22 | 显示全部楼层 来自 山东淄博
谢谢pasuka  ,抽空学习一下。
回复 不支持

使用道具 举报

 楼主| 发表于 2009-10-12 08:45:35 | 显示全部楼层 来自 山东淄博
以下实例选自Matlab中文论坛:http://www.ilovematlab.cn/thread-52145-1-5.html
该实例反应了Forcal的解题能力和运行效率。

实例:三房室模型给药后,药物在房室1和2,2和3间转运,并经房室3排出。假定转运均符合一级速率模型,则各房室药物量(X1,X2,X3)与时间t的关系如下:
dX1/dt=-K12*X1+K21*X2
dX2/dt=(-K21-K23)*X2+K12*X1+K32*X3
dX3/dt=(-K32-K30)*X3+K23*X2
已知初值t=0时:X1=100, X2=X3=0 。
实验值:
t=1: X1=90, X2=8,X3=2
t=3: X1=73, X2=19,X3=7
t=5: X1=60, X2=14,X3=23
求拟合参数K12,K21,K23,K32,和K30。
限制条件:K12,K21,K23,K32,和K30均大于零;X1+X2+X3小于等于100(总量不能超过给药量)。
拟合可以用非线形最小二乘法,即求取minΣ(y实验值-y真实值)2时的K值。
当然这个问题的结构相对简单,所以也可以求出各方程积分式,然后用EXCEL规划求解拟合。这是药物动力学中的方法。但是对于更复杂的系统,如十房室以上,积分式将非常复杂,手工求方程积分式几近不可能。

算法分析:用徐士良算法库XSLSF中的求n维极值的复形调优法函数cplx求最优参数值K12,K21,K23,K32,和K30,目标函数为理论值与实验值差的平方和。根据提供的微分方程初值,用连分式法对微分方程组积分一步函数pbs1求理论值。理论值与实验值差的平方和最小时获得参数的最优解。


  1. //Forcal代码
  2. //若长时间没有结果,按Ctrl+Alt+q退出Forcal运行
  3. i: OutVector(p:k,i)= k=FCDLen(p),printff{"\r\n"},i=0,(i<k).while{printff{"{1,r,14.6}",get[p,i]},i++},printff{"\r\n"}; //输出一维数组
  4. !using["XSLSF","sys"]; //使用命名空间XSLSF和sys
  5. f(t,X1,X2,X3,dX1,dX2,dX3::k12,k21,k23,k32,k30)={ //函数定义,连分式法对微分方程组积分一步函数pbs1中要用到
  6.   dX1=-k12*X1+k21*X2,
  7.   dX2=(-k21-k23)*X2+k12*X1+k32*X3,
  8.   dX3=(-k32-k30)*X3+k23*X2
  9. };
  10. t_i(hf,a,step,eps,t1,t2,x1,x2,x3:h,i)= //用于约束条件定义
  11. {
  12.     h=(t2-t1)/step,
  13.     {   pbs1[hf,t1,a,h,eps],  //连分式法对微分方程组积分一步函数pbs1,hf为函数f的句柄
  14.         t1=t1+h
  15.     }.until[abs(t1-t2)<h/2],
  16.     a.getra(0,&x1,&x2,&x3)
  17. };
  18. t_i_2(hf,a,step,eps,t1,t2,x_1,x_2,x_3:x1,x2,x3,h,i)= //用于计算目标函数
  19. {
  20.     h=(t2-t1)/step,
  21.     {   pbs1[hf,t1,a,h,eps],  //连分式法对微分方程组积分一步函数pbs1,hf为函数f的句柄
  22.         t1=t1+h
  23.     }.until[abs(t1-t2)<h/2],
  24.     a.getra(0,&x1,&x2,&x3),
  25.     (x1-x_1)^2+(x2-x_2)^2+(x3-x_3)^2
  26. };
  27. J(_k12,_k21,_k23,_k32,_k30:t1:hf,Array,step,eps,k12,k21,k23,k32,k30)={    //目标函数定义
  28.   k12=_k12,k21=_k21,k23=_k23,k32=_k32,k30=_k30,
  29.   t1=0, Array.setra(0,100,0,0),
  30.   t_i_2(hf,Array,step,eps: &t1, 1 : 90,  8,  2)+
  31.   t_i_2(hf,Array,step,eps: &t1, 3 : 73, 19,  7)+
  32.   t_i_2(hf,Array,step,eps: &t1, 5 : 60, 14, 23)
  33. };
  34. S(_k12,_k21,_k23,_k32,_k30,c0,c1,c2,d0,d1,d2,w0,w1,w2:t1,x1,x2,x3:hf,Array,step,eps,k12,k21,k23,k32,k30)=    //约束条件定义
  35. {
  36.   c0=0,         c1=0,         c2=0,
  37.   d0=100,       d1=100,       d2=100,
  38.   k12=_k12,k21=_k21,k23=_k23,k32=_k32,k30=_k30,
  39.   t1=0, Array.setra(0,100,0,0),
  40.   t_i(hf,Array,step,eps: &t1, 1 :  &x1, &x2, &x3), w0=x1+x2+x3,
  41.   t_i(hf,Array,step,eps: &t1, 3 :  &x1, &x2, &x3), w1=x1+x2+x3,
  42.   t_i(hf,Array,step,eps: &t1, 5 :  &x1, &x2, &x3), w2=x1+x2+x3
  43. };
  44. main(:a,b,alpha,_eps,k,x,xx,dx,i,tm:hf,Array,step,eps)=
  45. {
  46.     tm=clock(),
  47.     hf=HFor("f"),
  48.     Array=new[rtoi(real_s),rtoi(45)],
  49.     step=20,eps=1e-6, //step越大,eps越小越精确,用于积分一步函数pbs1
  50.     a=new[rtoi(real_s),rtoi(5),rtoi(EndType),1e-50,1e-50,1e-50,1e-50,1e-50], //存放常量约束条件中的变量的下界
  51.     b=new[rtoi(real_s),rtoi(5),rtoi(EndType),  1,    1,    1,    1,    1  ], //存放常量约束条件中的变量的上界
  52.     x=new[rtoi(real_s),rtoi(6),rtoi(EndType), 0.1,  0.1,  0.1,  0.1,  0.1 ], //其中前n个分量存放初始复形的第一个顶点坐标值(要求满足所有的约束条件),返回时存放极小值点各坐标值。最后一个分量返回极小值。
  53.     xx=new[rtoi(real_s),rtoi(6),rtoi(10)],
  54.     _eps=1e-10, alpha=1.01,k=800,dx=1e-4,   //_eps控制精度要求;alpha为反射系数;k为允许的最大迭代次数;dx为微小增量。需选择合适的alpha,_eps,k,dx值求解。
  55.     i=cplx[HFor("J"),HFor("S"),a,b,alpha,_eps,x,xx,k,dx],
  56.     printff{"\r\n实际迭代次数={1,r}\r\n",i},
  57.     OutVector[x],
  58.     delete[Array],delete[a],delete[b],delete[x],delete[xx] ,
  59.     printff{"\r\n程序运行{1,r}秒。\r\n",[clock()-tm]/1000}
  60. };
复制代码





结果:



  1. 实际迭代次数=661.
  2.       0.112939  7.11927e-002      0.346605    1.514e-007   9.5563e-003       33.4978
  3. 程序运行9.3279999999999994秒。
复制代码


    徐士良算法库XSLSF中的数值计算函数取自徐士良主编的《C常用算法程序集》第二版。在XSLSF中,Forcal仅对徐士良全部数值算法进行了封装,对算法本身未作更改。因而容易比较Forcal程序与C/C++程序的运行效率。




  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include "math.h"
  5. double k12,k21,k23,k32,k30;
  6. double Array[3];
  7. double aa[5]={1.0e-50,1.0e-50,1.0e-50,1.0e-50,1.0e-50};
  8. double bb[5]={   1,      1,      1,      1,      1   };
  9. double xx[6]={ 0.1,  0.1,  0.1,  0.1,  0.1};
  10. double xxx[6][10];
  11. double step, eps;
  12.   void gpbs1f(double t,double *y,int n,double *d)
  13.   {
  14.     d[0]=-k12*y[0]+k21*y[1];
  15.     d[1]=(-k21-k23)*y[1]+k12*y[0]+k32*y[2];
  16.     d[2]=(-k32-k30)*y[2]+k23*y[1];
  17.     return;
  18.   }
  19.   static void rkt1(double t,double h,int n,double *y,double *b,double *d,double *e)
  20.   { int i,k;
  21.     double a[4],tt;
  22.     a[0]=h/2.0; a[1]=a[0]; a[2]=h; a[3]=h;
  23.     gpbs1f(t,y,n,d);
  24.     for (i=0; i<=n-1; i++) { b[i]=y[i]; e[i]=y[i];}
  25.     for (k=0; k<=2; k++)
  26.       { for (i=0; i<=n-1; i++)
  27.           { y[i]=e[i]+a[k]*d[i];
  28.             b[i]=b[i]+a[k+1]*d[i]/3.0;
  29.           }
  30.         tt=t+a[k];
  31.         gpbs1f(tt,y,n,d);
  32.       }
  33.     for (i=0; i<=n-1; i++)
  34.       y[i]=b[i]+h*d[i]/6.0;
  35.     return;
  36.   }
  37.   void gpbs1(double t,double h,int n,double *y,double eps)
  38.   { int i,j,k,m,nn,it;
  39.     double x,hh,dd,q,p,g[10],*b,*d,*u,*v,*w,*e;
  40.     b=(double *)malloc(10*n*sizeof(double));
  41.     d=(double *)malloc(n*sizeof(double));
  42.     u=(double *)malloc(n*sizeof(double));
  43.     v=(double *)malloc(n*sizeof(double));
  44.     w=(double *)malloc(n*sizeof(double));
  45.     e=(double *)malloc(n*sizeof(double));
  46.     for (j=0; j<=n-1; j++) v[j]=y[j];
  47.     x=t; nn=1; hh=h; g[0]=hh;
  48.     rkt1(x,hh,n,y,w,d,e);
  49.     for (j=0; j<=n-1; j++)
  50.       { b[j]=y[j]; u[j]=y[j];}
  51.     k=1; it=1;
  52.     while (it==1)
  53.       { nn=nn+nn; hh=hh/2.0; it=0;
  54.         g[k]=hh;
  55.         for (j=0; j<=n-1; j++) y[j]=v[j];
  56.         t=x;
  57.         for (j=0; j<=nn-1; j++)
  58.           { rkt1(t,hh,n,y,w,d,e);
  59.             t=t+hh;
  60.           }
  61.         for (j=0; j<=n-1; j++)
  62.           { dd=y[j]; m=0;
  63.             for (i=0; i<=k-1; i++)
  64.               if (m==0)
  65.                 { q=dd-b[i*n+j];
  66.                   if (fabs(q)+1.0==1.0) m=1;
  67.                   else dd=(g[k]-g[i])/q;
  68.                 }
  69.             b[k*n+j]=dd;
  70.             if (m!=0) b[k*n+j]=1.0e+35;
  71.           }
  72.         for (j=0; j<=n-1; j++)
  73.           { dd=0.0;
  74.             for (i=k-1; i>=0; i--)
  75.               dd=-g[i]/(b[(i+1)*n+j]+dd);
  76.             y[j]=dd+b[j];
  77.           }
  78.         p=0.0;
  79.         for (j=0; j<=n-1; j++)
  80.           { q=fabs(y[j]-u[j]);
  81.             if (q>p) p=q;
  82.           }
  83.         if ((p>=eps)&&(k<7))
  84.           { for (j=0; j<=n-1; j++) u[j]=y[j];
  85.             k=k+1; it=1;
  86.           }
  87.       }
  88.     free(b); free(d); free(u); free(v); free(w); free(e);
  89.     return;
  90.   }
  91.   double rn(double *rr)
  92.   { int m;
  93.     double y,s,u,v;
  94.     s=65536.0; u=2053.0; v=13849.0;
  95.     *rr=u*(*rr)+v; m=(int)(*rr/s); *rr=*rr-m*s;
  96.     y=*rr/s;
  97.     return(y);
  98.   }
  99. void t_i(double *a,double step,double eps,double &t1,double t2,double &x1,double &x2,double &x3) //用于约束条件定义
  100. {   double h;
  101.     h=(t2-t1)/step;
  102.     do{   gpbs1(t1,h,3,a,eps);  //连分式法对微分方程组积分一步函数gpbs1
  103.         t1=t1+h;
  104.     }while(abs(t1-t2)>=h/2);
  105. x1=a[0];x2=a[1];x3=a[2];
  106. };
  107. double t_i_2(double *a,double step,double eps,double &t1,double t2,double x_1,double x_2,double x_3) //用于计算目标函数
  108. {   double h;
  109.     h=(t2-t1)/step;
  110.     do{   gpbs1(t1,h,3,a,eps);  //连分式法对微分方程组积分一步函数gpbs1
  111.         t1=t1+h;
  112.     }while(abs(t1-t2)>=h/2);
  113.     return (a[0]-x_1)*(a[0]-x_1)+(a[1]-x_2)*(a[1]-x_2)+(a[2]-x_3)*(a[2]-x_3);
  114. };
  115.   double jcplxf(double *x,int n)
  116.   { double t1,s=0;
  117.     k12=x[0];k21=x[1];k23=x[2];k32=x[3];k30=x[4];
  118.     t1=0; Array[0]=100; Array[1]=0; Array[2]=0;
  119.     s=s+ t_i_2(Array,step,eps,t1, 1 , 90,  8,  2);
  120. s=s+ t_i_2(Array,step,eps,t1, 3 , 73, 19,  7);
  121. return s+t_i_2(Array,step,eps,t1, 5 , 60, 14, 23);
  122.   }
  123.   void jcplxs(int n,int m,double *x,double *c,double *d,double *w)
  124.   { double x1,x2,x3,t1;
  125.     c[0]=0.0; c[1]=0.0; c[2]=0.0;
  126.     d[0]=100; d[1]=100; d[2]=100;
  127. k12=x[0];k21=x[1];k23=x[2];k32=x[3];k30=x[4];
  128. t1=0; Array[0]=100; Array[1]=0; Array[2]=0;
  129.     t_i(Array,step,eps,t1, 1 ,x1, x2, x3); w[0]=x1+x2+x3;
  130.     t_i(Array,step,eps,t1, 3 ,x1, x2, x3); w[1]=x1+x2+x3;
  131.     t_i(Array,step,eps,t1, 5 ,x1, x2, x3); w[2]=x1+x2+x3;
  132.     return;
  133.   }
  134.   int jcplx(int n,int m,double *a,double *b,double alpha,double eps,double *x,double *xx,int k,double dx)
  135.   {
  136.     int r,g,i,j,it,kt,jt,kk;
  137.     double fj,fr,fg,z,rr,*c,*d,*w,*xt,*xf;
  138.     c=(double *)malloc(m*sizeof(double));
  139.     d=(double *)malloc(m*sizeof(double));
  140.     w=(double *)malloc(m*sizeof(double));
  141.     xt=(double *)malloc(n*sizeof(double));
  142.     xf=(double *)malloc(n*sizeof(double));
  143.     rr=0.0;
  144.     for (i=0; i<=n-1; i++)
  145.       xx[i*n*2]=x[i];
  146.     xx[n*n*2]=jcplxf(x,n);
  147.     for (j=1; j<=2*n-1; j++)
  148.       { for (i=0; i<=n-1; i++)
  149.    { xx[i*n*2+j]=a[i]+(b[i]-a[i])*rn(&rr);
  150.             x[i]=xx[i*n*2+j];
  151.           }
  152.         it=1;
  153.         while (it==1)
  154.           { it=0; r=0; g=0;
  155.             while ((r<n)&&(g==0))
  156.               { if ((a[r]<=x[r])&&(b[r]>=x[r])) r=r+1;
  157.                 else g=1;
  158.               }
  159.             if (g==0)
  160.               { jcplxs(n,m,x,c,d,w);
  161.                 r=0;
  162.                 while ((r<m)&&(g==0))
  163.                   { if ((c[r]<=w[r])&&(d[r]>=w[r])) r=r+1;
  164.                     else g=1;
  165.                   }
  166.               }
  167.             if (g!=0)
  168.               { for (r=0; r<=n-1; r++)
  169.                   { z=0.0;
  170.                     for (g=0; g<=j-1; g++)
  171.                       z=z+xx[r*n*2+g]/(1.0*j);
  172.                     xx[r*n*2+j]=(xx[r*n*2+j]+z)/2.0;
  173.                     x[r]=xx[r*n*2+j];
  174.                   }
  175.                 it=1;
  176.               }
  177.             else xx[n*n*2+j]=jcplxf(x,n);
  178.           }
  179.       }
  180.     kk=1; it=1;
  181.     while (it==1)
  182.       { it=0;
  183.         fr=xx[n*n*2]; r=0;
  184.         for (i=1; i<=2*n-1; i++)
  185.           if (xx[n*n*2+i]>fr)
  186.             { r=i; fr=xx[n*n*2+i];}
  187.         g=0; j=0; fg=xx[n*n*2];
  188.         if (r==0)
  189.           { g=1; j=1; fg=xx[n*n*2+1];}
  190.         for (i=j+1; i<=2*n-1; i++)
  191.           if (i!=r)
  192.             if (xx[n*n*2+i]>fg)
  193.               { g=i; fg=xx[n*n*2+i];}
  194.         for (i=0; i<=n-1; i++)
  195.           { xf[i]=0.0;
  196.             for (j=0; j<=2*n-1; j++)
  197.               if (j!=r)
  198.                 xf[i]=xf[i]+xx[i*n*2+j]/(2.0*n-1.0);
  199.             xt[i]=(1.0+alpha)*xf[i]-alpha*xx[i*n*2+r];
  200.           }
  201.         jt=1;
  202.         while (jt==1)
  203.           { jt=0;
  204.             z=jcplxf(xt,n);
  205.             while (z>fg)
  206.               { for (i=0; i<=n-1; i++)
  207.                   xt[i]=(xt[i]+xf[i])/2.0;
  208.                 z=jcplxf(xt,n);
  209.               }
  210.             j=0;
  211.             for (i=0; i<=n-1; i++)
  212.               { if (a[i]>xt[i])
  213.                   { xt[i]=xt[i]+dx; j=1;}
  214.                 if (b[i]<xt[i])
  215.                   { xt[i]=xt[i]-dx; j=1;}
  216.               }
  217.             if (j!=0) jt=1;
  218.             else
  219.               { jcplxs(n,m,xt,c,d,w);
  220.                 j=0; kt=1;
  221.                 while ((kt==1)&&(j<m))
  222.                   { if ((c[j]<=w[j])&&(d[j]>=w[j])) j=j+1;
  223.                     else kt=0;
  224.                   }
  225.                 if (j<m)
  226.                   { for (i=0; i<=n-1; i++)
  227.                       xt[i]=(xt[i]+xf[i])/2.0;
  228.                     jt=1;
  229.                   }
  230.               }
  231.           }
  232.         for (i=0; i<=n-1; i++)
  233.           xx[i*n*2+r]=xt[i];
  234.         xx[n*n*2+r]=z;
  235.         fr=0.0; fg=0.0;
  236.         for (j=0; j<=2*n-1; j++)
  237.           { fj=xx[n*n*2+j];
  238.             fr=fr+fj/(2.0*n);
  239.             fg=fg+fj*fj;
  240.           }
  241.         fr=(fg-2.0*n*fr*fr)/(2.0*n-1.0);
  242.         if (fr>=eps)
  243.           { kk=kk+1;
  244.             if (kk<k) it=1;
  245.           }
  246.       }
  247.     for (i=0; i<=n-1; i++)
  248.       { x[i]=0.0;
  249.         for (j=0; j<=2*n-1; j++)
  250.           x[i]=x[i]+xx[i*n*2+j]/(2.0*n);
  251.       }
  252.     z=jcplxf(x,n); x[n]=z;
  253.     free(c); free(d); free(w);
  254.     free(xt); free(xf);
  255.     return(kk);
  256.   }

  257. int main(int argc, char *argv[])
  258. {
  259. clock_t tm;
  260. double _eps,alpha,dx;
  261. int k,i;
  262. tm=clock();
  263.     step=20;eps=1e-6; //step越大,eps越小越精确,用于积分一步的变步长欧拉方法
  264.     _eps=1e-10; alpha=1.01;k=800;dx=1e-4;   //_eps控制精度要求;alpha为反射系数;k为允许的最大迭代次数;dx为微小增量。需选择合适的alpha,_eps,k,dx值求解。
  265.     i=jcplx(5,3,aa,bb,alpha,_eps,xx,&xxx[0][0],k,dx);
  266.     printf("\r\n实际迭代次数=%d\r\n",i);
  267. printf("%12.6e, %12.6e, %12.6e, %12.6e, %12.6e, %12.6e\n",xx[0],xx[1],xx[2],xx[3],xx[4],xx[5]);
  268. printf("程序运行 %e 秒。\n", double(clock()-tm)/1000.0);
  269. }
复制代码


结果:


  1. 实际迭代次数=661
  2. 1.129389e-001, 7.119267e-002, 3.466046e-001, 1.513995e-007, 9.556298e-003, 3.349781e+001
  3. 程序运行 3.500000e+000 秒。
复制代码


可以看出,Forcal运行结果与C/C++完全一致,但效率约为C/C++的30%左右,是可以接受的。但Forcal程序代码的书写难度远远小于C/C++,可大幅提高用户的工作效率。
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2026-1-12 01:26 , Processed in 0.030009 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表