C++ main module for emicrom Package  1.0
EMMH_HysteresisFile.hpp
Go to the documentation of this file.
1 #include "EMMH_HysteresisFile.h"
2 
3 template<class T>
5  EMM_RealArray* Hext,
6  EMM_Array<T>* M,
7  tUIndex& n,
8  tUSInt& dim,
9  tUInteger& iData,
10  tUInteger& iHCycle,
11  tUSInt& s) const {
12 
13 
14  //return velue of the method
15  tBoolean succeeds=true;
16 
17  //init the last 1/2 cycle read index
18  iHCycle=0;
19 
20  //init the first index of the data of the half cycle c to compute
21  iData=0;
22 
23  //index of the data
24  tUInteger i=0;
25 
26 
27  //open the hysteresis file
28  ifstream fileHst(fileName.c_str(),ios::in);
29 
30  //number of steps of Hext
31  n=0;
32 
33  //indicates if the current data is found
34  tBoolean isCurrentDataFound=false;
35 
36  if (fileHst) {
37 
38  //number of lines
39  tUInteger numLine=0;
40 
41  // for reading line
42  tUInteger len=2048;
43  char line[len];
44 
45  // for analysing line
46  tUIndex nTokens=0;
47  tString token;
48  SP::CORE_String tokenizer=CORE_String::New();
49 
50  //dimension of M
51  tUSInt k;
52 
53 
54  //iterator on Hext
55  tReal *Hi=null;
56 
57  //iterator on M
58  T *Mi=null;
59 
60  //memory distance between 2 1/2 cycles for M
61  tUInteger ldM=0;
62 
63  //current 1/2 cycles read in a line
64  tUInteger nHCycles;
65 
66  //max number of 1/2 cycles
67  tUInteger nMaxHCycles;
68 
69  tBoolean isFirstHCyclesNumberRead=false;
70 
71 
72 
73  // data step for saving magnetism file
74  i=0;
75 
76  do {
77  //current line
78  numLine++;
79  // read line
80  fileHst.getline(line,len);
81 
82  //analyse the line
83  tokenizer->setString(line);
84  tokenizer->tokenize(": , \t");
85  nTokens=tokenizer->getTokensCount();
86 
87  //empty line
88  if (nTokens==0) continue;
89 
90  //read the first token
91  token=tokenizer->nextToken();
92 
93  //comment line
94  if (token.find("#")==0) continue;
95 
96 
97  //read the type of M
98  if ( (nTokens==4) && (n==0) ) {
99 
100  //read the number of data per 1/2 cycle
101  n=CORE_Integer::parseInt(token);
102 
103  //read the dim of M
104  dim=CORE_Integer::parseInt(tokenizer->nextToken());
105 
106  //read the maximum number of half cycles
107  nMaxHCycles=CORE_Integer::parseInt(tokenizer->nextToken());
108  //init the current data
109  iHCycle=0;
110  iData=0;
111 
112  //read the step for saving the equilibrium magnetism field
113  s=CORE_Integer::parseInt(tokenizer->nextToken());
114 
115  //set the size of H
116  if (Hext!=null) {
117  Hext->setSize(3*n);
118  Hi=&(*Hext)[0];
119  }
120 
121  //set the size of M
122  if (M!=null) {
123  M->setSize(dim*n*nMaxHCycles);
124 
125  //memory size between point at (i,iCycle) and point at (i-dim,iCycle+1)
126  ldM=(n-1)*dim;
127  } else {
128  ldM=0;
129  }
130 
131  } else {//read current line
132  if ((dim==0) || (n==0)) {
133  cout << "error in reading the hysteresis file: M type can not be read or no data found \n";
134  succeeds=false;
135  }
136 
137 
138  if (succeeds) {
139  if (nTokens>=3) {
140  //read H ext
141  if (Hext!=null) {
142  (*Hi)=CORE_Real::parseReal(token);
143  Hi++;
144  for (k=0;k<2;k++) {
145  token=tokenizer->nextToken();
146  (*Hi)=CORE_Real::parseReal(token);
147  Hi++;
148  }
149  } else {
150  tokenizer->nextToken();
151  tokenizer->nextToken();
152  }
153  nTokens-=3;
154 
155  //read M at step s for all 1/2 cycles
156  //index=d+dim*(i+n*iHCycle)
157  Mi=null;
158  if (M!=null) {
159  //verify number of tokens is ok
160  if (nTokens/dim>nMaxHCycles) throw EMM_Exception("emicrom/hysteresis",
161  "EMMH_HysteresisFile::load()",
162  "number of cycles ("+CORE_Integer::toString(nTokens/dim)+") is greater than this indicated in header:"+CORE_Integer::toString(nMaxHCycles));
163  Mi=&(*M)[dim*i];
164  nHCycles=0;
165  while (nTokens>=dim) {
166  nHCycles++;
167 
168  for (k=0;k<dim;k++) {
169  token=tokenizer->nextToken();
170  CORE_String::parse(token,*Mi);
171  Mi++;
172 
173  }
174  nTokens-=dim;
175  Mi+=ldM;
176  }//end loop on reading data for each data step
177  } else {
178  nHCycles=nTokens/dim;
179  }
180  //nHCycle is the number of half cycles read
181 
182 
183  //set the first number of half cycles computed
184  if (!isFirstHCyclesNumberRead){
185  if (nHCycles==0) {
186  //no cycles
187  iHCycle=0;
188  isCurrentDataFound=true;
189  } else {
190  iHCycle=nHCycles-1;
191  }
192  isFirstHCyclesNumberRead=true;
193  } else if ( (!isCurrentDataFound) && (nHCycles<iHCycle+1) ) {
194  //increment half cycle
195  iData=i;
196  isCurrentDataFound=true;;
197 
198  } else if ((!isCurrentDataFound) && (nHCycles>iHCycle+1)) {
199  //decrement half cycle
200  iData=i-1;
201  //half cycle to compute
202  iHCycle=nHCycles-1;
203  isCurrentDataFound=true;
204  }
205 
206 
207 
208  //next step
209  i++;
210 
211  } else {//end nTokends>=3
212  cout << "error in reading the hysteresis file:not enough data to read Hext \n";
213  succeeds=false;
214  }
215  }//end succeeds condition
216 
217  }//end reding current line
218  //stop if any of those conditions are fullfilled:
219  // - any error occurs
220  // - all the data has been read
221  // - end of file
222  // - max num lines reached
223  } while ( (succeeds) &&
224  ((n==0) || ( (n>0) && (i<n)) ) &&
225  ((Hext!=null) || !isCurrentDataFound) &&
226  (!fileHst.eof()) && (numLine<MAX_LINES) );
227 
228  //close the file
229  fileHst.close();
230  } else {
231  cout << "error in opening the file "<<fileName<<"\n";
232  succeeds=false;
233  }
234 
235 
236  if (!isCurrentDataFound) {
237  //all the data for the last half cycles has been computed
238  //set the next data to first data of next half cycle
239  iHCycle++;
240  if (iHCycle%2==0) iData=0;
241  else iData=n-1;
242  }
243 
244  return succeeds;
245 }
246 
247 template<class T>
249  const tString& comment,
250  const EMM_RealArray& Hext,
251  const EMM_Array<T>& M,
252  const tUSInt& dim,
253  const tUInteger& iData,
254  const tUInteger& iHCycle,
255  const tUSInt& s) const {
256 
257 
258  //interator on data
259  tUIndex i,n=Hext.getSize();
260 
261  //number of data
262  n/=dim;
263 
264  //cycles
265  tUSInt c,nMaxHCycles;
266 
268  tUSInt d;
269 
270  //compute max number of H Cycles
271  nMaxHCycles=(M.getSize()/(n*dim));
272 
273  //memory size between point at (i,iCycle) and point at (i-dim,iCycle+1)
274  tUIndex ldM=(n-1)*dim;
275 
276  //open the hysteresis file
277  ofstream fileHst(fileName.c_str(),ios::out);
278  if (fileHst) {
279  fileHst << "# hysteresis file modified by e-microm"<<endl;
280  fileHst << comment <<endl;
281  fileHst << "# N: number of data per half cycle"<<endl;
282  fileHst << "# D : dimension of the field per data"<<endl;
283  fileHst << "# nHCycles : number of half cycles"<<endl;
284  fileHst << "# S : steps number for saving equilibrium magnetism"<<endl;
285  fileHst<< n<<"\t"<<dim<<"\t"<<nMaxHCycles<<"\t"<<s<<endl;
286  fileHst << "# Hext : M^0_x M^0_y M^0_z M^1_x M^1_y M^1_z ..."<<endl;
287  //iterator on H
288  const tReal *Hi=&Hext[0];
289  //iterator on M
290  const T *Mci,*Mi=&M[0];
291  for (i=0;i<n;i++) {
292  //print Hext
293  for (d=0;d<3;d++) {
294  fileHst<<(*Hi)<<"\t";
295  Hi++;
296  }
297  fileHst<<":\t";
298 
299  Mci=Mi;
300  //save for all data value for half-cycle in [0,iHCycle[
301  for (c=0;c<iHCycle;c++) {
302  for (d=0;d<dim;d++) {
303  fileHst<<(*Mci)<<"\t";
304  Mci++;
305  }
306  Mci+=ldM;
307  }
308  //for last cycle iHCycle
309  //save all data in [0,iData] if iHycle is pair
310  //save all adat in [iData,n[ if iHcycle is impair
311  if (iHCycle%2==0) {
312  if (i<=iData) {
313  for (d=0;d<dim;d++) {
314  fileHst<<(*Mci)<<"\t";
315  Mci++;
316  }
317  }
318  } else {
319  if (i>=iData) {
320  for (d=0;d<dim;d++) {
321  fileHst<<(*Mci)<<"\t";
322  Mci++;
323  }
324  }
325  }
326 
327 
328  //all cycles with data saved
329  fileHst<<"\n";
330 
331  Mi+=dim;
332  }
333 
334  } else {
335  cout << "impossible to open the hysteresis file "<<fileName<<"\n";
336  return false;
337  }
338  return true;
339 }
340 
341 template<class T>
343  const EMM_Array<T>& M,
344  const tUSInt& dim,
345  const tUSInt& flowSize) const {
346 
347 
348  tString outFileName=inFileName+"~";
349 
350  tUSInt k;
351 
352  tUInteger i0,c0;
353  tUInteger i,c;
354  tUInteger nHCycles;
355 
356  tUIndex n;
357  tUSInt s;
358  tUSInt dim0;
359 
360  //load the current hysteresis data to fill
361  load(inFileName,null,(EMM_Array<T>*) null,n,dim0,i0,c0,s);
362 
363  if (dim0!=dim) {
364  throw EMM_Exception("emicrom/hsyteresis",
365  "EMMH_HysteresisFile::append(...)",
366  "incompatible hysteresis file "+inFileName+" dimension are not the same "+CORE_Integer::toString(dim0)+" with the append one "+CORE_Integer::toString(dim));
367  return false;
368  }
369 
370  //open the file for reading
371  ifstream iFileHst(inFileName.c_str(),ios::in);
372 
373  //open the file for writing
374  ofstream oFileHst(outFileName.c_str(),ios::out);
375 
376 
377  // the index of the point is as follow:
378  //index(i,c)=\sum_{k=0}^{k=c} u_k with u_0=i u_{2p}=2i+1 and u_{2p+1}=2*(n-1-i)+1
379  tUIndex index,index1,index0=i0;
380  for (c=1;c<=c0;c++) {
381  index0+=((c%2==1)?(2*(n-1-i0)+1):(2*i0+1));
382  }
383  index1=index0+flowSize;
384 
385  if (iFileHst && oFileHst) {
386 
387  //number of lines
388  tUInteger numLine=0;
389 
390  // for reading line
391  tUInteger len=2048;
392  char line[len];
393 
394  // for analysing line
395  tUIndex nTokens=0;
396  tString token;
397  SP::CORE_String tokenizer=CORE_String::New();
398 
399 
400  //iterator on M
401  const T *Mi;
402 
403 
404  //data
405  i=0;
406  tBoolean hasDataBeenRead=false;
407 
408  do {
409  //current line
410  numLine++;
411 
412  // read line
413  iFileHst.getline(line,len);
414 
415  //analyse the line
416  tokenizer->setString(line);
417  tokenizer->tokenize(": , \t");
418  nTokens=tokenizer->getTokensCount();
419 
420  //empty line
421  if (nTokens==0) continue;
422 
423  //read the first token
424  token=tokenizer->nextToken();
425 
426  //comment line
427  if (token.find("#")==0) {
428  oFileHst<<line<<"\n";
429  continue;
430  }
431 
432 
433  //read the type of M
434  if ( (nTokens==4) && (!hasDataBeenRead) ) {
435  //read the number of data per 1/2 cycle : ignored because already read
436  //n=CORE_Integer::parseInt(token);
437 
438  //read the dim of M
439  dim0=CORE_Integer::parseInt(tokenizer->nextToken());
440 
441  //read the maximum number of half cycles
442  tUInteger nMaxHCycles=CORE_Integer::parseInt(tokenizer->nextToken());
443  c=c0+(i0+flowSize)/n;
444  if (c>nMaxHCycles) nMaxHCycles=c;
445 
446  //read the step for saving the equilibrium magnetism field
447  //s=CORE_Integer::parseInt(tokenizer->nextToken());
448  //update the data
449  oFileHst<< n<<"\t"<<dim<<"\t"<<nMaxHCycles<<"\t"<<flowSize<<endl;
450  hasDataBeenRead=true;
451  continue;
452  } else {//read current line
453 
454 
455  if (nTokens>=3) {
456  //read H ext
457  tokenizer->nextToken();
458  tokenizer->nextToken();
459  nTokens-=3;
460 
461  //compute the number of cycles of the line
462  nHCycles=nTokens/dim;
463 
464  //write the cycles
465  oFileHst<<line;
466 
467  //compute the index of the last data read
468  index=0;
469  if (nHCycles>0) {
470  //c=0
471  index+=i;
472  //c>0
473  for (c=1;c<nHCycles;c++) {
474  index+=((c%2==1)?(2*(n-1-i)+1):(2*i+1));
475  }
476  }
477 
478  //compute the index of the next data to write
479  c=nHCycles;
480  if (c==0) index+=i;
481  else index+=((c%2==1)?(2*(n-1-i)+1):(2*i+1));
482 
483 
484  //fill the next datas
485  while ((index>=index0) && (index<index1)) {
486  Mi=&M[dim*(index-index0)];
487  for (k=0;k<dim;k++) {
488  oFileHst<<(*Mi)<<"\t";
489  Mi++;
490  }
491 
492  //index for the next cycle
493  c++;
494  index+=((c%2==1)?(2*(n-1-i)+1):(2*i+1));
495  }
496 
497  //next data
498  oFileHst<<"\n";
499  i++;
500 
501 
502  }//end data reading
503 
504  }//end reding current line
505  //stop if anu of those conditions are fullfilled:
506  // - all the data has been read
507  // - all the data has been written
508  // - end of file
509  // - max num lines reached
510  } while ( ((n==0) || ( (n>0) && (i<n)) )
511  && (!iFileHst.eof())
512  && (numLine<MAX_LINES) );
513 
514  //close the i/o files
515  iFileHst.close();
516  oFileHst.close();
517 
518 
519  } else {
520  cout << "impossible to open the hysteresis file "<<inFileName<<" for reading and "<<outFileName<<" for writing \n";
521  return false;
522 
523  }
524 
525 
526 
527  //rename the file
528  CORE_IO::mv(outFileName,inFileName);
529 
530  return true;
531 
532 
533 }
const tUIndex & getSize() const
return the size of the array for reading
Definition: CORE_Array.h:1018
static tLLInt parseInt(const tString &str)
return the integer associated to the string
Definition: CORE_Integer.cpp:102
static tBoolean mv(const tString &src, const tString &dest)
move file
Definition: CORE_IO.cpp:430
#define tUInteger
Definition: types.h:91
static void parse(const tString &str, tUChar &c)
parse unsigned char c in str
Definition: CORE_String.h:504
tBoolean load(EMM_RealArray &H, EMM_RealArray &M, tUSInt &D, tUInteger &i, tUInteger &c, tUSInt &s) const
load the file and fill the H values and the M values
Definition: EMMH_HysteresisFile.cpp:153
static tLDouble parseReal(const tString &str)
return the real associated to the string
Definition: CORE_Real.h:201
#define tUSInt
Definition: types.h:28
#define tBoolean
Definition: types.h:139
void setSize(const tUIndex &n)
set the size
Definition: CORE_Array.h:292
tBoolean append(const EMM_RealArray &M, const tUSInt &D, const EMM_RealArray &data, const tUSInt &dataDim, const tUSInt &n) const
append the data to the hysteresis file & relaxation return code
Definition: EMMH_HysteresisFile.cpp:120
tString toString() const
return the string associated to the integer
Definition: CORE_Integer.h:106
#define null
Definition: types.h:144
static const tUIndex MAX_LINES
Definition: EMMH_HysteresisFile.h:45
#define tUIndex
Definition: types.h:126
This class describes a real array.
Definition: EMM_RealArray.h:16
#define tString
Definition: types.h:135
this class describes the exceptions raised for E-MicromM package
Definition: EMM_Exception.h:14
static SP::CORE_String New()
create a class String
Definition: CORE_String.h:96
tBoolean save(const EMM_RealArray &Hext, const vector< tString > &dataNames, const tUInteger &nMaxHCycles, const tUSInt &flowSize) const
save all the external field for all hysteresis files:
Definition: EMMH_HysteresisFile.cpp:6
This class describes a general array.
Definition: EMM_Array.h:18
#define tReal
Definition: types.h:118