FEMM/femm/KCurve.cpp

330 lines
6.8 KiB
C++

// TKData.cpp : implementation file
//
#include "stdafx.h"
#include "femm.h"
#include "KCurve.h"
#include "BHPlot.h"
#include "TKDatafile.h"
#include <process.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTKData dialog
CTKData::CTKData(CWnd* pParent /*=NULL*/)
: CDialog(CTKData::IDD, pParent)
{
//{{AFX_DATA_INIT(CTKData)
m_Bdata = _T("");
m_Hdata = _T("");
//}}AFX_DATA_INIT
logplot=FALSE;
}
void CTKData::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTKData)
DDX_Text(pDX, IDC_BDATA, m_Bdata);
DDX_Text(pDX, IDC_HDATA, m_Hdata);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_BDATA, m_IDC_BDATA);
DDX_Control(pDX, IDC_HDATA, m_IDC_HDATA);
}
BEGIN_MESSAGE_MAP(CTKData, CDialog)
//{{AFX_MSG_MAP(CTKData)
ON_BN_CLICKED(IDC_PLOT_BHCURVE, OnPlotBHcurve)
ON_BN_CLICKED(IDC_LOGPLOT_BHCURVE, OnLogPlotBHcurve)
ON_BN_CLICKED(IDC_READ_BHCURVE, OnReadBhcurve)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTKData message handlers
void CTKData::StripTKData()
{
int k;
char *buff,*nptr,*endptr;
double z;
T.RemoveAll();
K.RemoveAll();
npts=0;
if((m_Bdata.GetLength()==0) || (m_Hdata.GetLength()==0)) return;
k=m_Bdata.GetLength()*2;
buff=(char *)calloc(k,sizeof(char));
strcpy(buff,m_Bdata);
nptr=buff;
while (sscanf(nptr,"%lf",&z)!=EOF){
z=strtod(nptr,&endptr );
if(nptr==endptr) nptr++; //catch special case
else nptr=endptr;
T.Add(z);
}
free(buff);
k=m_Hdata.GetLength()*2;
buff=(char *)calloc(k,sizeof(char));
strcpy(buff,m_Hdata);
nptr=buff;
while (sscanf(nptr,"%lf",&z)!=EOF){
z=strtod(nptr,&endptr );
if(nptr==endptr) nptr++;
else nptr=endptr;
K.Add(z);
}
npts=(int) T.GetSize();
if ((int) K.GetSize()<npts) npts=(int) K.GetSize();
SortCurve();
free(buff);
}
void CTKData::OnLogPlotBHcurve()
{
logplot=TRUE;
OnPlotBHcurve();
}
void CTKData::SortCurve()
{
int j;
double x;
BOOL bDone=FALSE;
if (npts<2) return;
while(bDone==FALSE)
{
for(j=1,bDone=TRUE;j<npts;j++)
{
if(T[j]<T[j-1])
{
bDone=FALSE;
x=T[j]; T[j]=T[j-1]; T[j-1]=x;
x=K[j]; K[j]=K[j-1]; K[j-1]=x;
}
}
}
}
double CTKData::GetK(double t)
{
int i,j;
if (npts==0) return 0;
if (npts==1) return K[0];
if (t<=T[0]) return K[0];
if (t>=T[npts-1]) return K[npts-1];
for(i=0,j=1;j<npts;i++,j++)
{
if((t>=T[i]) && (t<=T[j]))
{
return (K[i]+(K[j]-K[i])*(t-T[i])/(T[j]-T[i]));
}
}
return 0;
}
void CTKData::OnPlotBHcurve()
{
CBHPlot xyplot;
int i;
double t,dt;
BOOL logscale=logplot;
logplot=FALSE;
UpdateData();
StripTKData();
if (npts<2){
MsgBox("Must have at least 2 pairs of data points");
return;
}
// copy raw B-H data for plotting in comparison to interpolated curve
xyplot.NumPts=npts;
xyplot.Pts=(CComplex *)calloc(npts,sizeof(CComplex));
for(i=0;i<npts;i++) xyplot.Pts[i]=T[i]+I*K[i];
// get path to femmplot that we will need to display
// the plot of the B-H curve...
CString comline=((CFemmApp *)AfxGetApp())->GetExecutablePath();
// Actually evaluate all the points on the line...
if(xyplot.Create(101,2)==FALSE) return;
dt=(T[npts-1]-T[0])/100.;
for(i=0,t=T[0];i<=100;i++,t+=dt)
{
xyplot.M[i][0]=t;
xyplot.M[i][1]=GetK(t);
}
sprintf(xyplot.lbls[0],"T, K");
sprintf(xyplot.lbls[1],"k, W/(m*K)");
// Create the plot, send it to the clipboard, spawn viewer...
CMetaFileDC Meta;
Meta.CreateEnhanced(NULL,NULL,NULL,NULL);
xyplot.MakePlot(&Meta,logscale);
HENHMETAFILE hMeta=Meta.CloseEnhanced();
if (hMeta==NULL) MsgBox("No Handle...");
if (OpenClipboard()==FALSE)
MsgBox("Cannot access the Clipboard");
else{
EmptyClipboard();
if(SetClipboardData(CF_ENHMETAFILE,hMeta)==NULL)
{
MsgBox("Couldn't SetClipboardData");
}
CloseClipboard();
// fire up plot viewer;
// ((CFemmApp *)AfxGetApp())->CreateNewDocument(8);
// in this case call the external program rather than
// displaying in the window. Since dialog is running modal,
// it obscures the plotted BH curve--this is an annoying kludge.
char CommandLine[MAX_PATH];
sprintf(CommandLine,"%sfemmplot.exe", (const char *) ((CFemmApp *)AfxGetApp())->GetExecutablePath());
STARTUPINFO StartupInfo2 = {0};
PROCESS_INFORMATION ProcessInfo2;
StartupInfo2.cb = sizeof(STARTUPINFO);
CreateProcess(NULL,CommandLine, NULL, NULL, FALSE,0, NULL, NULL, &StartupInfo2, &ProcessInfo2);
CloseHandle(ProcessInfo2.hProcess);
CloseHandle(ProcessInfo2.hThread);
}
}
void CTKData::OnReadBhcurve()
{
// TODO: Add your control notification handler code here
CFileDialog *fname_dia;
CString infile;
fname_dia=new CFileDialog(
TRUE,
"dat | * ",
infile,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"Two column text data file (*.dat) | *.dat; *.DAT | All Files (*.*) | *.*||",
NULL);
if(fname_dia->DoModal()==IDCANCEL){
delete[] fname_dia;
return;
}
infile=fname_dia->GetPathName();
delete[] fname_dia;
CTKDatafile dlg;
if(dlg.DoModal()==IDCANCEL) return;
// read in data from text file;
m_Bdata.Empty();
m_Hdata.Empty();
char s[1024];
double t,k;
FILE *fp=fopen(infile,"rt");
if (fp==NULL){
MsgBox("problem opening data file");
return;
}
while(fgets(s,1024,fp)!=NULL)
{
if(dlg.TKOrder==0) sscanf(s,"%lf %lf",&t,&k);
else sscanf(s,"%lf %lf",&k,&t);
switch (dlg.TUnits)
{
case 1: // Celcius to Kelvin
t+=273.15;
break;
case 2: // Fahrenheit to Kelvin
t=5.*(t+459.67)/9.;
break;
case 3: // Rankine to Kelvin
t=5.*t/9.;
break;
default: // Kelvin
t*=1.;
break;
}
switch (dlg.KUnits)
{
case 1: // Btu/(ft*hr*F) to W/(m*K)
k*=1.73073466637139;
break;
case 2: // kcal/(m*hr*K) to W/(m*K)
k*=1.163;
break;
default: // W/(m*K)
k*=1.;
break;
}
sprintf(s,"%f\r\n",t); m_Bdata += s;
sprintf(s,"%f\r\n",k); m_Hdata += s;
}
SetDlgItemText(IDC_BDATA,m_Bdata);
SetDlgItemText(IDC_HDATA,m_Hdata);
fclose(fp);
}
BOOL CTKData::OnInitDialog()
{
CDialog::OnInitDialog();
// build string representation of the data out of numerical data
int i;
CString c;
m_Bdata.Empty();
m_Hdata.Empty();
for(i=0;i<npts;i++){
c.Format("%f\r\n",T[i]); m_Bdata+=c;
c.Format("%f\r\n",K[i]); m_Hdata+=c;
}
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CTKData::OnOK()
{
StripTKData();
CDialog::OnOK();
}