override public bool RunCalculation() { double * buf1, buf2; double wr, wi; double StartThickness = CurThickness; DateTime start; TimeSpan period; int i, iSlice = 0, iWave = 0; if ((ThWaves == null) || (ThWaves.Length == 0)) { return(true); } if ((double)ThWaves[iWave] <= CurThickness) { bool result = ((LastSavedWave = SaveWav(CurThickness)) != null); iWave++; Console.WriteLine("\rWave at " + CurThickness.ToString("######0.00") + "A unloaded " + result + " "); } start = DateTime.Now; while (iWave < ThWaves.Length) { iSlice = (int)(iSlice % NSlices); //Apply PG buf1 = data; buf2 = SliList[iSlice]; for (i = 0; i < M * N * 2; i += 2) { wr = *buf1; wi = *(buf1 + 1); *buf1 = wr * *buf2 - wi * *(buf2 + 1); *(buf1 + 1) = wr * *(buf2 + 1) + wi * *buf2; buf1++; buf1++; buf2++; buf2++; } //Apply Propagator SFT_direct.MakeSFT(data); buf1 = data; buf2 = PropList[iSlice]; for (i = 0; i < M * N * 2; i += 2) { wr = *buf1; wi = *(buf1 + 1); *buf1 = wr * *buf2 - wi * *(buf2 + 1); *(buf1 + 1) = wr * *(buf2 + 1) + wi * *buf2; buf1++; buf1++; buf2++; buf2++; } CurThickness += (double)ThSlices[iSlice]; if ((double)ThWaves[iWave] <= CurThickness) { if (IsSaveSTEM) { SaveSTEM(iWave); } if (IsSaveDiffractions) { Console.WriteLine("\rDiffraction at " + CurThickness.ToString("######0.00") + "A unloaded " + (SaveDiffraction(CurThickness) != null) + " "); } } SFT_backward.MakeSFT(data); period = DateTime.Now - start; if (!IsSaveSTEM) { Console.Write("\rPropagated " + CurThickness.ToString("######0.00") + "A at a speed of " + ((double)((CurThickness - StartThickness) * TimeSpan.TicksPerSecond / period.Ticks * 3600)).ToString("###0.000") + "A/h "); } if ((double)ThWaves[iWave] <= CurThickness) { iWave++; if (IsSaveWaves) { Console.WriteLine("\rWave at " + CurThickness.ToString("######0.00") + "A unloaded " + ((LastSavedWave = SaveWav(CurThickness)) != null) + " "); } } iSlice++; } return(true); }
override public bool RunCalculation() { float progress; DateTime start; TimeSpan period; double StartThickness = CurThickness; int i, iSlice = 0, iWave = 0; if ((ThWaves == null) || (ThWaves.Length == 0)) { return(true); } if ((double)ThWaves[iWave] <= CurThickness) { bool result = ((LastSavedWave = SaveWav(CurThickness)) != null); iWave++; Console.WriteLine("\rWave at " + CurThickness.ToString("######0.00") + "A unloaded " + result + " "); } if ((PotType == MSProject.PotTypes.PG_curve_TV_pullZ) || (PotType == MSProject.PotTypes.PG_curve_DW_pullZ)) { hanwidth = 8; hanning = new double[hanwidth]; nn = Math.Min(N, (uint)Math.Pow(2, Math.Ceiling(Math.Log(((atrad + 0.5) / a * N + hanwidth) / (1.0 - 2.0 / hanwidth), 2)) + 1)); mm = Math.Min(M, (uint)Math.Pow(2, Math.Ceiling(Math.Log(((atrad + 0.5) / b * M + hanwidth) / (1.0 - 2.0 / hanwidth), 2)) + 1)); atSFT_forward = new SFT(); atSFT_backward = new SFT(); atM = new MemMan(); if (!atM.Allocate(nn * mm * 2 * sizeof(double))) { return(false); } if (!atM.Lock(0, nn * mm * 2 * sizeof(double))) { return(false); } buf = (double *)atM.LockAddress; atSFT_forward.MakePlan(buf, nn, mm, 1); atSFT_backward.MakePlan(buf, nn, mm, -1); lambda = 0.387818 / Math.Sqrt(E / 1000.0 * (1.0 + 0.978459e-3 * E / 1000)); // E in V K = lambda * Math.Sqrt(1.0 + Math.Pow((0.0242621 / lambda), 2)); nninner = (uint)Math.Min(nn, (uint)(atrad) / a * N * 2 + Math.Max(1, nn / 2 - hanwidth - (uint)(atrad) / a * N)); mminner = (uint)Math.Min(mm, (uint)(atrad) / b * M * 2 + Math.Max(1, mm / 2 - hanwidth - (uint)(atrad) / b * M)); // nninner=(uint)Math.Min(nn,(uint)(atrad)/a*N*2) ; // mminner=(uint)Math.Min(mm,(uint)(atrad)/b*M*2) ; offix = (int)(nn - nninner); offiy = (int)(mm - mminner) / 2; for (i = 0; i < hanwidth; i++) { hanning[i] = (Math.Cos(i * Math.PI / hanwidth) + 1) * 0.5; } } start = DateTime.Now; while (iWave < ThWaves.Length) { iSlice = (int)(iSlice % NSlices) + 1; // Load Slice if (!LoadSlice(iSlice)) { return(false); } // apply Phase Gratting if (NAtoms > 0) { if ((PotType == MSProject.PotTypes.PG_DT_TV_periodic) || (PotType == MSProject.PotTypes.PG_DT_TV_cut) || (PotType == MSProject.PotTypes.PG_curve_TV_periodic) || (PotType == MSProject.PotTypes.PG_curve_TV_cut) || (PotType == MSProject.PotTypes.PG_curve_TV_pullZ)) { // некорректно работает с gam!=90 MusliRandom vibr = new MusliRandom(); for (i = 0; i < NAtoms; i++) { x[i] *= a; y[i] *= b; vibr.StDevX = vibr.StDevY = Math.Sqrt(DW[i] * 0.5) / (2.0 * Math.PI); vibr.Vobble(ref x[i], ref y[i]); if (PotType == MSProject.PotTypes.PG_curve_TV_pullZ) { z[i] += vibr.NextGauss(); } if (x[i] < 0) { x[i] += a; } if (x[i] >= a) { x[i] -= a; } if (y[i] < 0) { y[i] += b; } if (y[i] >= b) { y[i] -= b; } } } fixed(double *_x = x, _y = y, _dw = DW, _ads = ads, _occ = occ) { fixed(int *_type_ = type_, _type = type) { switch (PotType) { case MSProject.PotTypes.PG_DT_DW_periodic: PG_rs_DT_DW_periodic(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _dw, _ads, _occ, _type, data, &progress); break; case MSProject.PotTypes.PG_DT_DW_cut: PG_rs_DT_DW_cutpot(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _dw, _ads, _occ, _type, data, &progress); break; case MSProject.PotTypes.PG_curve_DW_periodic: PG_rs_curve_DW_periodic(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _ads, _occ, _type_, CurveHolder, CurveLength, dela, data, &progress); break; case MSProject.PotTypes.PG_curve_DW_cut: PG_rs_curve_DW_cutpot(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _ads, _occ, _type_, CurveHolder, CurveLength, dela, data, &progress); break; case MSProject.PotTypes.PG_DT_TV_periodic: PG_rs_DT_TV_periodic(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _ads, _occ, _type, data, &progress); break; case MSProject.PotTypes.PG_DT_TV_cut: PG_rs_DT_TV_cutpot(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _ads, _occ, _type, data, &progress); break; case MSProject.PotTypes.PG_curve_TV_periodic: PG_rs_curve_TV_periodic(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _ads, _occ, _type_, CurveHolder, CurveLength, dela, data, &progress); break; case MSProject.PotTypes.PG_curve_TV_cut: PG_rs_curve_TV_cutpot(a, b, gam, E, atrad, N, M, NAtoms, _x, _y, _ads, _occ, _type_, CurveHolder, CurveLength, dela, data, &progress); break; case MSProject.PotTypes.PG_curve_DW_pullZ: PG_rs_pullZ(); break; case MSProject.PotTypes.PG_curve_TV_pullZ: PG_rs_pullZ(); break; default: Console.WriteLine("Phase Gratting " + PotType.ToString() + " is not supported in " + this.ToString()); break; } } } } //Apply Propagator SFT_direct.MakeSFT(data); ApplyPropagator(a, b, gam, CurSliThickness, E, X_tilt_crystal, Y_tilt_crystal, N, M, data, &progress); CurThickness += CurSliThickness; if ((double)ThWaves[iWave] <= CurThickness) { if (IsSaveSTEM) { SaveSTEM(iWave); } if (IsSaveDiffractions) { Console.WriteLine("\rDiffraction at " + CurThickness.ToString("######0.00") + "A unloaded " + (SaveDiffraction(CurThickness) != null) + " "); } } SFT_backward.MakeSFT(data); period = DateTime.Now - start; if (!IsSaveSTEM) { Console.Write("\rPropagated " + NAtoms + " atoms, at total " + CurThickness.ToString("######0.00") + "A at a speed of " + ((double)((CurThickness - StartThickness) * TimeSpan.TicksPerSecond / period.Ticks * 3600)).ToString("###0.0") + "A/h "); } if ((double)ThWaves[iWave] <= CurThickness) { iWave++; if (IsSaveWaves) { Console.WriteLine("\rWave at " + CurThickness.ToString("######0.00") + "A unloaded " + ((LastSavedWave = SaveWav(CurThickness)) != null) + " "); } } } // calculation cycle return(true); }
override public void StartCalculations() { DateTime start; string ostr; int iSTEMline, iSTEMpoint; TimeSpan period; start = DateTime.Now; Console.WriteLine("\n****************** MS with reused potentials started ********************"); // Создание планов FFT Console.WriteLine("\nCreating FFT plans for " + N + "*" + M + " transformations"); SFT_backward.MakePlan(data, N, M, -1); SFT_direct.MakePlan(data, N, M, 1); Calc.a = a; Calc.b = b; Calc.gam = gam; Calc.N = N; Calc.M = M; Calc.E = E; Calc.data = data; Calc.NSlices = NSlices; Calc.ThSlices = ThSlices; Calc.IsSaveWaves = IsSaveWaves; Calc.IsSaveDiffractions = IsSaveDiffractions; Calc.IsSaveSTEM = (IniWaveType == MSProject.IniWaveTypes.STEMshift); Calc.SFT_direct = SFT_direct; Calc.SFT_backward = SFT_backward; Console.WriteLine("\nInitial wave is " + IniWaveType.ToString()); // int iE, iBT, iBS, iCA, iDf, iCs, iCT ; // moved to MyProject class definition for (iE = 0; iE < Emat.Length; iE++) { Calc.E = E = Emat[iE]; // Расчет и сохранение слоев if (!GeneratePG()) { Console.WriteLine("Can't create slices, exiting"); return; } for (iCT = 0; iCT < Math.Max(CrystalTilt.Length, 1); iCT++) { try { X_tilt_crystal = CrystalTilt[iCT][0] / 1000.0; Y_tilt_crystal = CrystalTilt[iCT][1] / 1000.0; } catch { Y_tilt_crystal = 0.0; } // создание пропагаторов GenerateProps(); Calc.SliList = SliList; Calc.PropList = PropList; for (iBT = 0; iBT < Math.Max(BeamTilt.Length, 1); iBT++) { X_beamtilt = Y_beamtilt = 0; if ((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift)) { try { X_beamtilt = BeamTilt[iBT][0] / 1000.0; Y_beamtilt = BeamTilt[iBT][1] / 1000.0; } catch { } } if (IniWaveType == MSProject.IniWaveTypes.PlaneWave) { try { X_beamtilt = BeamTilt[iBT][0]; Y_beamtilt = BeamTilt[iBT][1]; } catch { } } for (iBS = 0; iBS < (((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift))?Math.Max(BeamShift.Length, 1):1); iBS++) { if ((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift)) { try { X_beamshift = BeamShift[iBS][0]; Y_beamshift = BeamShift[iBS][1]; } catch { X_beamshift = Y_beamshift = 0.5; } } for (iCA = 0; iCA < (((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift))?Math.Max(ConvAngles.Length, 1):1); iCA++) { if ((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift)) { try { ConvAngle = ConvAngles[iCA][0]; ConvAngleInner = ConvAngles[iCA][1]; } catch { ConvAngle = 0.3; ConvAngleInner = 0; } } for (iCs = 0; iCs < (((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift))?Math.Max(Csmat.Length, 1):1); iCs++) { if ((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift)) { try { Cs = Csmat[iCs]; } catch { Cs = 0; } } for (iDf = 0; iDf < (((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift))?Math.Max(Dfmat.Length, 1):1); iDf++) { if ((IniWaveType == MSProject.IniWaveTypes.Converged) || (IniWaveType == MSProject.IniWaveTypes.STEMshift)) { try { Df = Dfmat[iDf]; } catch { Df = 0; } } if ((IniWaveType == MSProject.IniWaveTypes.STEMshift)) { iSTEMline = (int)Math.Floor((double)iBS / STEM_N); iSTEMpoint = iBS % STEM_N; if ((iSTEMpoint == 0) && (iCA == 0) && (iCs == 0) && (iDf == 0) && (iCT == 0)) { ostr = "\nLine " + iSTEMline + " (" + STEM_M + ")\n#"; } else { ostr = "#"; } } else { ostr = "\n*** " + (E / 1000.0).ToString("###0.0") + "kV"; ostr += ", CT(" + X_tilt_crystal.ToString("0.0###") + "," + Y_tilt_crystal.ToString("0.0###") + ")"; ostr += ", BT(" + X_beamtilt.ToString("0.0###") + "," + Y_beamtilt.ToString("0.0###") + ")"; ostr += "\n*** BS(" + X_beamshift.ToString("0.0###") + "," + Y_beamshift.ToString("0.0###") + ")"; ostr += ", CA(" + ConvAngle.ToString("0.0###") + "," + ConvAngleInner.ToString("0.0###") + ")"; ostr += ", Df" + Df.ToString("###0.0") + "A"; ostr += ", Cs" + (Cs / 1e7).ToString("###0.0") + "mm\n"; } Console.Write(ostr); // Создание начальной волны if (!CreateInitialWave()) { Console.WriteLine("Can't create initial wave, exiting"); return; } Calc.CurThickness = StartThickness; if (IsCalcAll) { this.ThWaves = new double[] { c + StartThickness - 0.00001 } } ; Calc.ThWaves = ThWaves; // Начало мултислайса Calc.RunCalculation(); } // Df cycle } // Cs cycle } // Convergence angle cycle } // beam shift cycle } // beam tilt cycle } // crystal tilt cycle } // E cycle if (IsContinue) { System.IO.File.Copy(Calc.LastSavedWave, Path.Combine(this.WorkingDirectoryName, "last.wav"), true); } if (IniWaveType == IniWaveTypes.STEMshift) { FlushSTEMfile(); } period = DateTime.Now - start; Console.WriteLine("\n****** MS finished, total time " + period.ToString() + " ********************"); } bool GeneratePG() { int i, j, k; MemMan iM; uint NMMs; float progress; int[] PropSliTable = new int[NSlices]; Props = new ArrayList(); SliList = new double *[NSlices]; PropList = new double *[NSlices]; for (i = 0; i < NSlices; i++) { for (j = 0; j < Props.Count; j++) { if (Math.Abs((double)Props[j] - (double)ThSlices[i]) < 0.000001) { break; } } if (j == Props.Count) { j = Props.Add(ThSlices[i]); } PropSliTable[i] = j; } PropsP = new double *[Props.Count]; MMList = new ArrayList((int)(NSlices + Props.Count)); for (i = 0; i < NSlices + Props.Count; i++) { iM = new MemMan(); if (iM.Allocate(MemRequested())) { MMList.Add(iM); } else { break; } } NMMs = (uint)MMList.Count; if (NMMs < NSlices + Props.Count) { Console.WriteLine("Can't allocate all data in memory, only " + NMMs + " pages are available, " + (NSlices + Props.Count) + " requested,\nuse inline calculation"); return(false); } for (i = 0; i < NSlices; i++) { Console.WriteLine("Creating slice number " + i.ToString("0000") + " from " + (uint)NASlices[i] + " atoms using " + PotType.ToString()); //((MemMan)MMList[i]).Lock(0,MemRequested()) ; SliList[i] = (double *)((MemMan)MMList[i]).BaseAddress; if ((uint)NASlices[i] > 0) { ExtractSlice(i); fixed(double *_x = x, _y = y, _dw = DW, _ads = ads, _occ = occ) { fixed(int *_type_ = type_, _type = type) { switch (PotType) { case PotTypes.rs_DT_DW_periodic: Potential_rs_DT_DW_periodic(a, b, gam, atrad, N, M, (uint)NASlices[i], _x, _y, _dw, _ads, _occ, _type, SliList[i], &progress); break; case PotTypes.rs_DT_DW_cut: Potential_rs_DT_DW_cutpot(a, b, gam, atrad, N, M, (uint)NASlices[i], _x, _y, _dw, _ads, _occ, _type, SliList[i], &progress); break; case PotTypes.rs_curve_DW_periodic: Potential_rs_curve_DW_periodic(a, b, gam, atrad, N, M, (uint)NASlices[i], _x, _y, _ads, _occ, _type_, (double *)PotCurve.BaseAddress, CurveLength, dela, SliList[i], &progress); break; case PotTypes.rs_curve_DW_cut: Potential_rs_curve_DW_cutpot(a, b, gam, atrad, N, M, (uint)NASlices[i], _x, _y, _ads, _occ, _type_, (double *)PotCurve.BaseAddress, CurveLength, dela, SliList[i], &progress); break; case PotTypes.rec_DT_DW: Potential_rec_DT_DW(a, b, gam, Nmult, Mmult, N, M, (uint)NASlices[i], 0, M, _x, _y, _dw, _ads, _occ, _type, SliList[i], &progress); SFT_backward.MakeSFT(SliList[i]); break; case PotTypes.rec_curve_DW: Potential_rec_curve_DW(a, b, gam, Nmult, Mmult, N, M, (uint)NASlices[i], 0, M, _x, _y, _ads, _occ, _type_, (double *)PotCurve.BaseAddress, CurveLength, ds, SliList[i], &progress); SFT_backward.MakeSFT(SliList[i]); break; default: Console.WriteLine("Potential " + PotType.ToString() + " is not supported"); return(false); } } } } if (IsSaveSlices) { SaveSlice(i); } } if (IsPotRec) { a *= Nmult; b *= Mmult; } //Создание PG из слайсов double lambda = 0.387818 / Math.Sqrt(E / 1000.0 * (1.0 + 0.978459e-3 * E / 1000)); // E in V double K = lambda * Math.Sqrt(1.0 + Math.Pow((0.0242621 / lambda), 2)); if (IsPotRec) { K *= (N * M); } for (i = 0; i < NSlices; i++) { double *pbuf = SliList[i]; double aR, aI; for (j = 0; j < M; j++) { for (k = 0; k < N; k++) { aR = K * *pbuf; aI = Math.Exp(-*(pbuf + 1) * K); *pbuf = Math.Cos(aR) * aI; *(++pbuf) = -Math.Sin(aR) * aI; pbuf++; } } // y-cycle } Atoms = null; // free a memory occupied by the model GC.Collect(); for (i = 0; i < Props.Count; i++) { PropsP[i] = (double *)((MemMan)MMList[(int)(i + NSlices)]).BaseAddress; } for (i = 0; i < NSlices; i++) { PropList[i] = PropsP[PropSliTable[i]]; } return(true); } bool GenerateProps() { int i; float progress; for (i = 0; i < Props.Count; i++) { Console.WriteLine("Creating propagator for " + ((double)Props[i]).ToString("##0.000000") + " A"); CreatePropagator(a, b, gam, (double)Props[i], E, X_tilt_crystal, Y_tilt_crystal, N, M, PropsP[i], &progress); } return(true); } void ExtractSlice(int i) { uint nas = (uint)NASlices[i]; x = new double[(int)nas]; y = new double[(int)nas]; DW = new double[(int)nas]; ads = new double[(int)nas]; occ = new double[(int)nas]; type = new int[(int)nas]; type_ = new int[(int)nas]; int j = 0; foreach (AtomRec at in Atoms) { if (at.sn == i) { x[j] = at.x; y[j] = at.y; DW[j] = at.DW; ads[j] = at.ads; occ[j] = at.occ; type[j] = at.type; type_[j] = at.type_; j++; } } } /// <summary> /// Saves slices in real space /// </summary> /// <returns></returns> bool SaveSlice(int iSlice) // save slices in real space { // a*Nmult, b*Mmult FileRW fN; string lwd, SavedFilename; lwd = Path.Combine(WorkingDirectoryName, "Slice stack"); if (!Directory.Exists(lwd)) { try { Directory.CreateDirectory(lwd); } catch (Exception e) { Console.WriteLine("Can't create working directory:\n" + e.ToString()); return(false); } } SavedFilename = Path.Combine(lwd, "Slice_" + iSlice.ToString("0000") + ".slice"); if ((fN = FileRW.Open(SavedFilename, FileRW.Action.CreateAlways, FileRW.Access.Write)) != null) { byte[] sout = new byte[160]; string Sout; uint nw; nw = fN.Write(SliList[iSlice], N * M * (uint)2); if (nw != N * M * (uint)2 * sizeof(double)) { // add code to find and display the reason Console.WriteLine("Only " + nw + " bytes out of " + N * M * (uint)2 * sizeof(double) + " are written to\n" + SavedFilename); fN.Close(); SavedFilename = null; return(false); } Sout = String.Format("___ {0,12:g10} {1,12:g10} {2,12:g10} {3,10:g5} {4,10:g5} {5,10:g8} {6,10:g} {7,00000} {8,00000} {9,10:g} {10,5:n0} ", a * Nmult, b * Mmult, ThSlices[iSlice], Math.PI / 2.0, Math.PI / 2.0, gam, -1.0, N, M, iSlice, NSlices); for (int i = 0; i < 160; i++) { sout[i] = (i < Sout.Length)?System.Convert.ToByte(Sout[i]):(byte)0; } fN.Write(sout, 160); fN.Close(); return(true); } else { SavedFilename = null; return(false); } } }