//----------------------------------------------------------------------------- HADT MGL_EXPORT mgl_datac_column(HCDT dat, const char *eq) { const mglData *dd=dynamic_cast<const mglData *>(dat); std::vector<mglDataA*> list; if(dd && dd->id.length()>0) for(size_t i=0;i<dd->id.length();i++) { mglDataT *col = new mglDataT(*dat); col->SetInd(i,dd->id[i]); list.push_back(col); } const mglDataC *dc=dynamic_cast<const mglDataC *>(dat); if(dc && dc->id.length()>0) for(size_t i=0;i<dc->id.length();i++) { mglDataT *col = new mglDataT(*dat); col->SetInd(i,dc->id[i]); list.push_back(col); } if(list.size()==0) return 0; // no named columns mglDataV *t = new mglDataV(dat->GetNy(),dat->GetNz()); t->s=L"#$mgl"; list.push_back(t); mglDataC *r = new mglDataC; r->Set(mglFormulaCalcC(eq,list)); for(size_t i=0;i<list.size();i++) delete list[i]; return r; }
//----------------------------------------------------------------------------- void MGL_EXPORT mgl_datac_fill_eq(HMGL gr, HADT d, const char *eq, HCDT vdat, HCDT wdat, const char *opt) { if(vdat && vdat->GetNN()!=d->GetNN()) return; // incompatible dimensions if(wdat && wdat->GetNN()!=d->GetNN()) return; gr->SaveState(opt); std::wstring s = d->Name(); d->Name(L"u"); mglDataV x(d->nx,d->ny,d->nz, gr->Min.x,gr->Max.x,'x'); x.Name(L"x"); mglDataV y(d->nx,d->ny,d->nz, gr->Min.y,gr->Max.y,'y'); y.Name(L"y"); mglDataV z(d->nx,d->ny,d->nz, gr->Min.z,gr->Max.z,'z'); z.Name(L"z"); mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x'); i.Name(L"i"); mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y'); j.Name(L"j"); mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z'); k.Name(L"k"); mglDataV r(d->nx,d->ny,d->nz); r.Name(L"#$mgl"); mglData v(vdat), w(wdat); v.Name(L"v"); w.Name(L"w"); std::vector<mglDataA*> list; list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(&r); list.push_back(d); list.push_back(&v); list.push_back(&w); list.push_back(&i); list.push_back(&j); list.push_back(&k); d->Move(mglFormulaCalcC(eq,list)); d->Name(s.c_str()); gr->LoadState(); }
//----------------------------------------------------------------------------- HADT MGL_EXPORT mgl_datac_momentum(HCDT dat, char dir, const char *how) { if(!how || !(*how) || !strchr("xyz",dir)) return 0; long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz(); mglDataV x(nx,ny,nz, 0,1,'x'); x.s=L"x"; mglDataV y(nx,ny,nz, 0,1,'y'); y.s=L"y"; mglDataV z(nx,ny,nz, 0,1,'z'); z.s=L"z"; mglDataC u(dat); u.s=L"u"; // NOTE slow !!! std::vector<mglDataA*> list; list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(&u); mglDataC res=mglFormulaCalcC(how,list); mglDataC *b=0; if(dir=='x') { b=new mglDataC(nx); #pragma omp parallel for for(long i=0;i<nx;i++) { register dual i1=0,i0=0; for(long j=0;j<ny*nz;j++) { register dual u=dat->vthr(i+nx*j); i0 += u; i1 += u*res.a[i+nx*j]; } b->a[i] = i0!=mreal(0) ? i1/i0 : 0; } } if(dir=='y') { b=new mglDataC(ny); #pragma omp parallel for for(long i=0;i<ny;i++) { register dual i1=0,i0=0; for(long k=0;k<nz;k++) for(long j=0;j<nx;j++) { register dual u=dat->v(j,i,k); i0 += u; i1 += u*res.a[j+nx*(i+ny*k)]; } b->a[i] = i0!=mreal(0) ? i1/i0 : 0; } } if(dir=='z') { long nn=nx*ny; b=new mglDataC(nz); #pragma omp parallel for for(long i=0;i<nz;i++) { register dual i1=0,i0=0; for(long j=0;j<nn;j++) { register dual u=dat->vthr(j+nn*i); i0 += u; i1 += u*res.a[j+nn*i]; } b->a[i] = i0!=mreal(0) ? i1/i0 : 0; } } return b; }
//----------------------------------------------------------------------------- // return values: 0 - OK, 1 - wrong arguments, 2 - wrong command, 3 - string too long, 4 -- unclosed string int mglParser::Parse(mglGraph *gr, std::wstring str, long pos) { if(Stop || gr->NeedStop()) return 0; curGr = gr->Self(); std::wstring arg[1024]; str=mgl_trim_ws(str); long n,k=0,m=0,mm=0,res; // try parse ':' -- several commands in line for(n=0;n<long(str.length());n++) { if(str[n]=='\'' && (n==0 || str[n-1]!='\\')) k++; if(k%2) continue; if(str[n]=='(') m++; if(str[n]==')') m--; if(str[n]=='{') mm++; if(str[n]=='}') mm--; if(str[n]=='#') break; if((str[n]==':' || str[n]=='\n') && k%2==0 && m==0 && mm==0) { res=Parse(gr,str.substr(0,n),pos); if(!res) res=Parse(gr,str.substr(n+1),pos); return res; } } if(k%2 || m || mm) return 4; // strings is not closed // define parameters or start cycle res = ParseDef(str); if(res) return res-1; // parse arguments (parameters $1, ..., $9) PutArg(str,false); str=mgl_trim_ws(str); std::wstring opt; for(k=0;k<1024;k++) // parse string to substrings (by spaces) { n = mglFindArg(str); if(n<1) // this is option { if(str[-n]==';') opt = str.substr(-n+1); if(n<0) str = str.substr(0,-n); break; } arg[k] = str.substr(0,n); str = mgl_trim_ws(str.substr(n+1)); } // try to find last argument if(str[0]!=0 && str[0]!='#' && str[0]!=';') { arg[k] = str; k++; } if(k<1) n =0; else { // fill arguments by its values mglArg *a = new mglArg[k]; FillArg(gr, k, arg, a); // execute first special (program-flow-control) commands if(!skip() && !arg[0].compare(L"stop")) { Stop = true; delete []a; return 0; } if(!arg[0].compare(L"func")) { Stop = true; delete []a; return 0; } n = FlowExec(gr, arg[0].c_str(),k-1,a); if(n) { delete []a; return n-1; } if(skip()) { delete []a; return 0; } if(!arg[0].compare(L"load")) { int n = a[0].type==1?0:1; a[0].s.assign(a[0].w.begin(),a[0].w.end()); if(!n) mgl_parser_load(this,a[0].s.c_str()); delete []a; return n; } if(!arg[0].compare(L"define")) { if(k==3) { DeleteVar(arg[1].c_str()); // force to delete variable with the same name mglNum *v=AddNum(arg[1].c_str()); if(arg[2][0]=='!') // complex number is added { HADT dd = mglFormulaCalcC(arg[2].substr(1),this, DataList); v->d=NAN; v->c = dd->a[0]; delete dd; } else { HMDT dd = mglFormulaCalc(arg[2],this, DataList); v->c = v->d = dd->a[0]; delete dd; } } delete []a; return k==3?0:1; } if(!arg[0].compare(L"rkstep")) { int res=1; if(k>2 && a[0].type==1 && a[1].type==1) { std::wstring a1 = arg[1], a2=arg[2]; res = 0; if(a1[0]=='\'') a1 = a1.substr(1,a1.length()-2); if(a2[0]=='\'') a2 = a2.substr(1,a2.length()-2); mgl_rk_step_w(this, a1.c_str(), a2.c_str(), (k>=3 && a[2].type==2)?a[2].v:1); } delete []a; return res; } if(!arg[0].compare(L"call")) { n = 1; if(a[0].type==1) { int na=0; a[0].s.assign(a[0].w.begin(),a[0].w.end()); n=-IsFunc(a[0].w.c_str(),&na); if(n && k!=na+2) { char buf[64]; snprintf(buf,64,"Bad arguments for %ls: %ld instead of %d\n", a[0].w.c_str(),k-2,na); buf[63]=0; gr->SetWarn(-1,buf); n = 1; } else if(n) { mglFnStack fn; fn.pos = pos; for(int i=0;i<10;i++) { fn.par[i] = par[i]; par[i]=L""; } for(int i=1;i<k-1;i++) AddParam(i,arg[i+1].c_str()); fn_stack.push_back(fn); n--; } else if(AllowFileIO) // disable external scripts if AllowFileIO=false { FILE *fp = fopen(a[0].s.c_str(),"rt"); if(fp) { register int i; mglParser *prs = new mglParser(AllowSetSize); prs->DataList.swap(DataList); prs->NumList.swap(NumList); prs->Cmd=Cmd; for(i=10;i<30;i++) prs->AddParam(i,par[i].c_str()); prs->Execute(gr,fp); for(i=10;i<30;i++) AddParam(i,prs->par[i].c_str()); DataList.swap(prs->DataList); NumList.swap(prs->NumList); prs->Cmd=0; delete prs; fclose(fp); } else n=1; } } delete []a; return n; } if(!arg[0].compare(L"for")) { n = 1; char ch = arg[1][0]; int r = ch-'0'; if(ch>='a' && ch<='z') r = 10+ch-'a'; // int r = int(a[0].v); if(arg[1][1]==0 && (r>=0 && r<40)) { if(a[1].type==0) { n=0; fval[r] = *(a[1].d); fval[r].nx *= fval[r].ny*fval[r].nz; } else if(a[1].type==2 && a[2].type==2 && a[2].v>a[1].v) { mreal step = a[3].type==2?a[3].v:1; mm = int(step>0 ? (a[2].v-a[1].v)/step : 0); if(mm>0) { n=0; fval[r].Create(mm+1); for(int ii=0;ii<mm+1;ii++) fval[r].a[ii] = a[1].v + step*ii; } } if(n==0) { for(int i=39;i>0;i--) { for_stack[i]=for_stack[i-1]; if_for[i]=if_for[i-1]; } for_stack[0] = r+1; fval[r].nz = pos; if_for[0]=if_pos; wchar_t buf[32]; mglprintf(buf,32,L"%g",fval[r].a[0]); AddParam(r, buf); fval[r].ny = 1; } } delete []a; return n; } // alocate new arrays and execute the command itself n = PreExec(gr, k, arg, a); if(n>0) n--; else if(!arg[0].compare(L"setsize") && !AllowSetSize) n = 2; else n = Exec(gr, arg[0].c_str(),k-1,a, arg[1].c_str(), opt.c_str()); delete []a; } // delete temporary data arrays for(size_t i=0;i<DataList.size();i++) if(DataList[i] && DataList[i]->temp) { mglDataA *u=DataList[i]; DataList[i]=0; delete u; } return n; }
//----------------------------------------------------------------------------- // convert substrings to arguments void mglParser::FillArg(mglGraph *gr, int k, std::wstring *arg, mglArg *a) { register long n; for(n=1;n<k;n++) { mglDataA *v; mglNum *f; a[n-1].type = -1; if(arg[n][0]=='|') a[n-1].type = -1; else if(arg[n][0]=='\'') // this is string (simplest case) { a[n-1].type = 1; std::wstring &w=arg[n],f; wchar_t buf[32]; long i,i1,ll=w.length(); for(i=1;i<ll;i++) { if(w[i]=='\'') { if(i==ll-1) continue; i++; i1 = i; if(w[i1]==',') i1++; if(w[i1]==0) continue; for(;i<ll && w[i]!='\'';i++); if(i>i1) { if(w[i1]=='!') { HADT d = mglFormulaCalcC(w.substr(i1+1,i-i1-(w[i]=='\''?1:0)), this, DataList); mreal di = imag(d->a[0]), dr = real(d->a[0]); if(di>0) mglprintf(buf,32,L"%g+%gi",dr,di); else if(di<0) mglprintf(buf,32,L"%g-%gi",dr,-di); // TODO use \u2212 ??? else mglprintf(buf,32,L"%g",dr); a[n-1].w += buf; delete d; } else { HMDT d = mglFormulaCalc(w.substr(i1,i-i1-(w[i]=='\''?1:0)), this, DataList); mglprintf(buf,32,L"%g",d->a[0]); a[n-1].w += buf; delete d; } } } else a[n-1].w += w[i]; } } else if(arg[n][0]=='{') { // this is temp data mglData *u=new mglData; std::wstring s = arg[n].substr(1,arg[n].length()-2); a[n-1].w = u->s = L"/*"+s+L"*/"; a[n-1].type = 0; ParseDat(gr, s, *u); a[n-1].d = u; u->temp=true; DataList.push_back(u); } else if((v = FindVar(arg[n].c_str()))!=0) // try to find normal variables (for data creation) { a[n-1].type=0; a[n-1].d=v; a[n-1].w=v->s; } else if((f = FindNum(arg[n].c_str()))!=0) // try to find normal number (for data creation) { a[n-1].type=2; a[n-1].d=0; a[n-1].v=f->d; a[n-1].c=f->c; a[n-1].w = f->s; } else if(arg[n][0]=='!') // complex array is asked { // parse all numbers and formulas by unified way HADT d = mglFormulaCalcC(arg[n].substr(1), this, DataList); if(d->GetNN()==1) { if(CheckForName(arg[n].substr(1))) { a[n-1].type = 2; a[n-1].v = d->v(0); a[n-1].c = d->a[0]; } else { a[n-1].type = 0; a[n-1].d = AddVar(arg[n].c_str()); } delete d; } else { a[n-1].w = L"/*"+arg[n]+L"*/"; d->temp=true; DataList.push_back(d); a[n-1].type = 0; a[n-1].d = d; } } else { // parse all numbers and formulas by unified way HMDT d = mglFormulaCalc(arg[n], this, DataList); if(d->GetNN()==1) { if(CheckForName(arg[n])) { a[n-1].type = 2; a[n-1].c = a[n-1].v = d->v(0); } else { a[n-1].type = 0; a[n-1].d = AddVar(arg[n].c_str()); } delete d; } else { a[n-1].w = L"/*"+arg[n]+L"*/"; d->temp=true; DataList.push_back(d); a[n-1].type = 0; a[n-1].d = d; } } } }
void MGL_EXPORT mgl_rk_step_w(HMPR pr, const wchar_t *Eqs, const wchar_t *Vars, mreal dt) { const std::wstring eqs(Eqs); const std::wstring vars(Vars); std::vector<mglRKdat> rkv; size_t iv=0,jv=0,ie=0,je=0; while(1) { iv = vars.find(';',jv); ie = eqs.find(';',je); mglDataA *vv=mgl_parser_find_varw(pr,vars.substr(jv,iv-jv).c_str()); std::wstring eq = eqs.substr(je,ie-je).c_str(); if(vv) rkv.push_back(mglRKdat(vv, eq )); jv = iv+1; je = ie+1; if(iv==std::wstring::npos || ie==std::wstring::npos) break; } for(size_t i=0;i<rkv.size();i++) rkv[i].allocate(); mreal hh = dt/2; for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cmplx) rk.c1.Move(mglFormulaCalcC(rk.e, pr, pr->DataList)); else rk.d1.Move(mglFormulaCalc(rk.e, pr, pr->DataList)); } for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cc) { long n = rk.cc->GetNN(); dual a = hh*rk.c1.a[0]; if(rk.c1.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + hh*rk.c1.a[j]; else #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a; } if(rk.dd) { long n = rk.dd->GetNN(); mreal a = hh*rk.d1.a[0]; if(rk.d1.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + hh*rk.d1.a[j]; else #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a; } } for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cmplx) rk.c2.Move(mglFormulaCalcC(rk.e, pr, pr->DataList)); else rk.d2.Move(mglFormulaCalc(rk.e, pr, pr->DataList)); } for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cc) { long n = rk.cc->GetNN(); dual a = hh*rk.c2.a[0]; if(rk.c2.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + hh*rk.c2.a[j]; else #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a; } if(rk.dd) { long n = rk.dd->GetNN(); mreal a = hh*rk.d2.a[0]; if(rk.d2.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + hh*rk.d2.a[j]; else #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a; } } for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cmplx) rk.c3.Move(mglFormulaCalcC(rk.e, pr, pr->DataList)); else rk.d3.Move(mglFormulaCalc(rk.e, pr, pr->DataList)); } for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cc) { long n = rk.cc->GetNN(); dual a = dt*rk.c3.a[0]; if(rk.c3.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + dt*rk.c3.a[j]; else #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a; } if(rk.dd) { long n = rk.dd->GetNN(); mreal a = dt*rk.d3.a[0]; if(rk.d3.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + dt*rk.d3.a[j]; else #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a; } } for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cmplx) rk.c4.Move(mglFormulaCalcC(rk.e, pr, pr->DataList)); else rk.d4.Move(mglFormulaCalc(rk.e, pr, pr->DataList)); } for(size_t i=0;i<rkv.size();i++) { mglRKdat &rk = rkv[i]; if(rk.cc) { long n = rk.cc->GetNN(); dual a = (rk.c1.a[0]+rk.c2.a[0]+mreal(2)*(rk.c3.a[0]+rk.c4.a[0]))*(dt/6); if(rk.c1.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + (rk.c1.a[j]+rk.c2.a[j]+mreal(2)*(rk.c3.a[j]+rk.c4.a[j]))*(dt/6); else #pragma omp parallel for for(long j=0;j<n;j++) rk.cc->a[j] = rk.cin.a[j] + a; } if(rk.dd) { long n = rk.dd->GetNN(); mreal a = (rk.d1.a[0]+rk.d2.a[0]+2*(rk.d3.a[0]+rk.d4.a[0]))*(dt/6); if(rk.d1.GetNN()==n) #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + (rk.d1.a[j]+rk.d2.a[j]+2*(rk.d3.a[j]+rk.d4.a[j]))*(dt/6); else #pragma omp parallel for for(long j=0;j<n;j++) rk.dd->a[j] = rk.din.a[j] + a; } } }
HADT MGL_EXPORT mgl_parser_calc_complexw(HMPR pr, const wchar_t *formula) { return mglFormulaCalcC(formula,pr, pr->DataList); }