/* Spectroscopic Toolkit version 1.95, april 21, 2011. See headerfile ST.c06_HBASE for more documentation. Copyright (c) 2000-2008 - Pieter Suurmond Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any person wishing to distribute modifications to the Software is requested to send the modifications to the original developer so that they can be incorporated into the canonical version. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include /* Standard headers. */ #include #include /* For memcpy(). */ #include #include "ST_pconv.h" /* Defines structure of the binary database-file. */ #include "c06_JEBASE.h" #include "ST_wavelets.h" /* Need forward declaration of */ #include "c00.h" /* ENGINE before including c00.h. */ /*----------------------------------------------------------------------------------*/ #define kMAX_JDIF 1 /* Limits, there are more. */ #define kMAX_JLOW 12 /* Limits, there are more. */ #define kMAX_ELOW 3 /* There are no more. */ #define kMAX_EDIF 88 /* There are no more. */ JDIF_SERIES* init_JEBASE(FILE* msg) { JDIF_SERIES* result; int DJ, LJ, LE, mLE; long linesCollected = 0L, linesSkipped = 0L; FILE* pbinDatabaseFP; short atomicNumber, ionizationLevel; pieterPacked pbinBuff; long double Evalue; unsigned char memErr = 0; result = (JDIF_SERIES*)malloc(sizeof(JDIF_SERIES)); if (result == NULL) goto nomem; result->numJDIF = kMAX_JDIF; /* DIMENSION. */ result->JLOWseries = (JLOW_SERIES*)malloc(kMAX_JDIF * sizeof(JLOW_SERIES)); if (result->JLOWseries == NULL) { nomem: if (msg != NULL) fprintf(msg, "Not enough memory.\n"); eexit: free_JEBASE(&result); /* Safe to call when object not fully filled/allocated. */ return result; } for (DJ=0; DJJLOWseries[DJ].numJLOW = kMAX_JLOW; /* DIMENSION. */ result->JLOWseries[DJ].ELOWseries = (ELOW_SERIES*)malloc(kMAX_JLOW * sizeof(ELOW_SERIES)); if (result->JLOWseries[DJ].ELOWseries == NULL) memErr = 255; /* But go on to set all array pointers to NULL (at malloc()-failures. */ for (LJ=0; LJJLOWseries[DJ].ELOWseries[LJ].numELOW = 0; /* DIMENSION to 0, not kMAX_ELOW! */ result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries = malloc(kMAX_ELOW * sizeof(EDIF_SERIES)); if (!result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries) memErr = 255; /* But go on to set all array pointers to NULL (at malloc()-failures. */ for (LE=0; LEJLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF = 0; /* DIMENSION to 0, not kMAX_EDIF! */ result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line = malloc(kMAX_EDIF * sizeof(pieterPacked)); if (!result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line) memErr = 255; /* But go on to set all array pointers to NULL (at malloc()-failures. */ } } } if (memErr) goto nomem; pbinDatabaseFP = fopen(kST_bin_base, "rb"); if (pbinDatabaseFP == NULL) { if (msg != NULL) fprintf(msg, "Failed to open file '%s'!\n", kST_bin_base); goto eexit; } if (msg != NULL) fprintf(msg, "Running init_JEBASE():\n"); while (fread(&pbinBuff, sizeof(pbinBuff), 1, pbinDatabaseFP)) { atomicNumber = pbinBuff.ELEM / 100; ionizationLevel = pbinBuff.ELEM - (100 * atomicNumber); if ((atomicNumber == 1) && (!ionizationLevel)) /* Skip IONS. */ { DJ = (int)(pbinBuff.UPP.J - pbinBuff.LOW.J) - 1; /* Determine DIF_J. (never negative?!) */ LJ = (int)(pbinBuff.LOW.J - 0.5); /* Determine LOW_J. */ if ((DJ < kMAX_JDIF) && (LJ < kMAX_JLOW) && (DJ >= 0)) /* Within range? Skip negative and 0 DJs. */ { for (LE=0; LEJLOWseries[DJ].ELOWseries[LJ].numELOW; LE++) /* Determine LOW_E. */ { /* But also keep it ordered on LOW.E! */ Evalue = result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line[0].LOW.E; if (Evalue == pbinBuff.LOW.E) goto cpy; /* Add to this coordinate. */ if (Evalue > pbinBuff.LOW.E) { /* Then we've got to insert! */ result->JLOWseries[DJ].ELOWseries[LJ].numELOW++; if (result->JLOWseries[DJ].ELOWseries[LJ].numELOW > kMAX_ELOW) goto LEexceed; for (mLE=result->JLOWseries[DJ].ELOWseries[LJ].numELOW; mLE>LE; mLE--) memcpy(&(result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[mLE]), &(result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[mLE-1]), sizeof(EDIF_SERIES)); /* Move all one up. */ goto cpy; } } /* Append at the end if not found (or nothing in the array yet): */ result->JLOWseries[DJ].ELOWseries[LJ].numELOW++; /* New low energy-level added. */ if (result->JLOWseries[DJ].ELOWseries[LJ].numELOW > kMAX_ELOW) { LEexceed: if (msg != NULL) fprintf(msg, "ELOW exceeding maximum (%d)!\n", kMAX_ELOW); clexit: free_JEBASE(&result); goto clf; } cpy: memcpy(&result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line [result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF], &pbinBuff, sizeof(pieterPacked)); result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF++; /* New line added. */ if (result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF > kMAX_EDIF) { if (msg != NULL) fprintf(msg, "EDIF exceeding maximum (%d)!\n", kMAX_EDIF); goto clexit; } linesCollected++; } else { linesSkipped++; /* if (msg) fprintf(msg, "init_JEBASE skipped DJ=%d, LJ=%d.\n", DJ, LJ); */ } } } if (msg != NULL) { fprintf(msg, "Collected %ld lines, skipped %ld lines:\n", linesCollected, linesSkipped); for (DJ=0; DJnumJDIF; DJ++) for (LJ=0; LJJLOWseries[DJ].numJLOW; LJ++) for (LE=0; LEJLOWseries[DJ].ELOWseries[LJ].numELOW; LE++) fprintf(msg, " DJ=%d LJ=%d LE=%d DE=%d lines\n", DJ, LJ, LE, result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF); } clf: fclose(pbinDatabaseFP); return result; } /*----------------------------------------------------------------------------------*/ #define kMAX_JDIF_HeP 1 /* Limits, there are more? */ #define kMAX_JLOW_HeP 12 /* 6 There are no more */ #define kMAX_ELOW_HeP 3 /* There are no more */ #define kMAX_EDIF_HeP 88 /* 79 There are no more */ JDIF_SERIES* init_JEBASE_HeP(FILE* msg) { JDIF_SERIES* result; int DJ, LJ, LE, mLE; long linesCollected = 0L, linesSkipped = 0L; FILE* pbinDatabaseFP; short atomicNumber, ionizationLevel; pieterPacked pbinBuff; long double Evalue; unsigned char memErr = 0; result = (JDIF_SERIES*)malloc(sizeof(JDIF_SERIES)); if (result == NULL) goto nomem; result->numJDIF = kMAX_JDIF_HeP; /* DIMENSION. */ result->JLOWseries = (JLOW_SERIES*)malloc(kMAX_JDIF_HeP * sizeof(JLOW_SERIES)); if (result->JLOWseries == NULL) { nomem: if (msg != NULL) fprintf(msg, "Not enough memory.\n"); eexit: free_JEBASE(&result); /* Safe to call when object not fully filled/allocated. */ return result; } for (DJ=0; DJJLOWseries[DJ].numJLOW = kMAX_JLOW_HeP; /* DIMENSION. */ result->JLOWseries[DJ].ELOWseries = (ELOW_SERIES*)malloc(kMAX_JLOW_HeP * sizeof(ELOW_SERIES)); if (!result->JLOWseries[DJ].ELOWseries) memErr = 255; /* But go on to set all array pointers to NULL (at malloc()-failures. */ for (LJ=0; LJJLOWseries[DJ].ELOWseries[LJ].numELOW = 0; /* DIMENSION to 0, not kMAX_ELOW! */ result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries = malloc(kMAX_ELOW_HeP * sizeof(EDIF_SERIES)); if (!result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries) memErr = 255; /* But go on to set all array pointers to NULL (at malloc()-failures. */ for (LE=0; LEJLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF = 0; /* DIMENSION to 0, not kMAX_EDIF! */ result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line = malloc(kMAX_EDIF_HeP * sizeof(pieterPacked)); if (!result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line) memErr = 255; /* But go on to set all array pointers to NULL (at malloc()-failures. */ } } } if (memErr) goto nomem; pbinDatabaseFP = fopen(kST_bin_base, "rb"); if (pbinDatabaseFP == NULL) { if (msg != NULL) fprintf(msg, "Failed to open file '%s'!\n", kST_bin_base); goto eexit; } if (msg != NULL) fprintf(msg, "Running init_JEBASE_HeP():\n"); while (fread(&pbinBuff, sizeof(pbinBuff), 1, pbinDatabaseFP)) { atomicNumber = pbinBuff.ELEM / 100; ionizationLevel = pbinBuff.ELEM - (100 * atomicNumber); if ((atomicNumber == 2) && (ionizationLevel == 1)) /* He+. */ { DJ = (int)(pbinBuff.UPP.J - pbinBuff.LOW.J) - 1; /* Determine DIF_J. (never negative?!) */ LJ = (int)(pbinBuff.LOW.J - 0.5); /* Determine LOW_J. */ if ((DJ < kMAX_JDIF_HeP) && (LJ < kMAX_JLOW_HeP) && (DJ >= 0)) /* Within range? Skip negative and 0 DJs. */ { for (LE=0; LEJLOWseries[DJ].ELOWseries[LJ].numELOW; LE++) /* Determine LOW_E. */ { /* But also keep it ordered on LOW.E! */ Evalue = result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line[0].LOW.E; if (Evalue == pbinBuff.LOW.E) goto cpy; /* Add to this coordinate. */ if (Evalue > pbinBuff.LOW.E) { /* Then we've got to insert! */ result->JLOWseries[DJ].ELOWseries[LJ].numELOW++; if (result->JLOWseries[DJ].ELOWseries[LJ].numELOW > kMAX_ELOW_HeP) goto LEexceed; for (mLE=result->JLOWseries[DJ].ELOWseries[LJ].numELOW; mLE>LE; mLE--) memcpy(&(result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[mLE]), &(result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[mLE-1]), sizeof(EDIF_SERIES)); /* Move all one up. */ goto cpy; } } /* Append at the end if not found (or nothing in the array yet): */ result->JLOWseries[DJ].ELOWseries[LJ].numELOW++; /* New low energy-level added. */ if (result->JLOWseries[DJ].ELOWseries[LJ].numELOW > kMAX_ELOW_HeP) { LEexceed: if (msg != NULL) fprintf(msg, "ELOW exceeding maximum (%d)!\n", kMAX_ELOW_HeP); clexit: free_JEBASE(&result); goto clf; } cpy: memcpy(&result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line [result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF], &pbinBuff, sizeof(pieterPacked)); result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF++; /* New line added. */ if (result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF > kMAX_EDIF_HeP) { if (msg != NULL) fprintf(msg, "EDIF exceeding maximum (%d)!\n", kMAX_EDIF_HeP); goto clexit; } linesCollected++; } else { linesSkipped++; /* if (msg) fprintf(msg, "init_JEBASE skipped DJ=%d, LJ=%d.\n", DJ, LJ); */ } } } if (msg != NULL) { fprintf(msg, "Collected %ld He+ lines, skipped %ld lines:\n", linesCollected, linesSkipped); for (DJ=0; DJnumJDIF; DJ++) for (LJ=0; LJJLOWseries[DJ].numJLOW; LJ++) for (LE=0; LEJLOWseries[DJ].ELOWseries[LJ].numELOW; LE++) fprintf(msg, " DJ=%d LJ=%d LE=%d DE=%d lines\n", DJ, LJ, LE, result->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].numEDIF); } clf: fclose(pbinDatabaseFP); return result; } /*---------------------------------------------------------------------*/ pieterPacked* ask_JEBASE(JDIF_SERIES* JE, int dj, int lj, int le, int de) { pieterPacked* result = (pieterPacked*)NULL; if (JE != NULL) { if ((dj >= 0) && (dj < JE->numJDIF) && (lj >= 0) && (lj < JE->JLOWseries[dj].numJLOW) && (le >= 0) && (le < JE->JLOWseries[dj].ELOWseries[lj].numELOW) && (de >= 0) && (de < JE->JLOWseries[dj].ELOWseries[lj].EDIFseries[le].numEDIF)) result = &(JE->JLOWseries[dj].ELOWseries[lj].EDIFseries[le].line[de]); } return result; } /*-----------------------------*/ void free_JEBASE(JDIF_SERIES** j) { int DJ, LJ, LE; if ((j != NULL) && (*j != NULL)) { if ((*j)->JLOWseries) { for (DJ=0; DJJLOWseries[DJ].ELOWseries) /* numJDIF-field in the struct! */ { for (LJ=0; LJJLOWseries[DJ].ELOWseries[LJ].EDIFseries) { for (LE=0; LEJLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line) free((*j)->JLOWseries[DJ].ELOWseries[LJ].EDIFseries[LE].line); } free((*j)->JLOWseries[DJ].ELOWseries[LJ].EDIFseries); } } free((*j)->JLOWseries[DJ].ELOWseries); } } free((*j)->JLOWseries); } free(*j); } }