From 45ca59110dafdb3910f1d206479758cbc59bccd7 Mon Sep 17 00:00:00 2001 From: jz8u17 <j.zhan@soton.ac.uk> Date: Thu, 8 Apr 2021 12:50:10 +0100 Subject: [PATCH] Add license, reformat code, update ReadMe --- .vscode/settings.json | 5 + README.md | 15 +- hibernus_validation/hibernus/config.h | 5 - hibernus_validation/hibernus/hibernus.c | 7 + hibernus_validation/hibernus/hibernus.h | 23 +-- model/LICENSE | 23 +++ model/Makefile | 4 - model/README.md | 82 +++++++--- model/costfunction.c | 116 +++++++------- model/harv_stor.c | 193 ++++++++++++----------- model/harv_stor_compare.c | 154 +++++++++---------- model/harv_stor_division.c | 157 +++++++++---------- model/harv_stor_range.c | 195 +++++++++++------------- model/harv_stor_tradeoff.c | 152 +++++++++--------- model/model.c | 175 ++++++++++----------- model/model.h | 83 +++++----- model/rs_to_ram.c | 55 +++---- model/show_period.c | 63 -------- model/stor_constcurrent.c | 118 +++++++------- 19 files changed, 801 insertions(+), 824 deletions(-) create mode 100644 .vscode/settings.json delete mode 100755 hibernus_validation/hibernus/config.h create mode 100644 model/LICENSE delete mode 100644 model/show_period.c diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..cc134d0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "cstdlib": "c" + } +} \ No newline at end of file diff --git a/README.md b/README.md index 492ef9b..9ee7dec 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,17 @@ Three sets of software are provided here: - A *finegrain* model used for simulating forward progress of intermittent computing systems with energy harvesting conditions (dynamic supply current). - Embedded software (adapted [Hibernus](https://ieeexplore.ieee.org/abstract/document/6960060?casa_token=MKSfvesOIMsAAAAA:srUgSqoEAtmTTJ65Re7vh3uyq9a7D6DXrOLPzgNndRZFQ9hSgMUiPTCB2gzIij1olI7lhvU)) used for experimental validation. -Results can be found in the paper published (*---link to be provided---*) and the corresponding [dataset](https://eprints.soton.ac.uk/447811/). +Presentations and results can be found in the [paper](https://ieeexplore.ieee.org/document/9386252) with the same title published in IEEE TCAD (doi: [10.1109/TCAD.2021.3068946](https://doi.org/10.1109/TCAD.2021.3068946)) and the corresponding [dataset](https://eprints.soton.ac.uk/447811/). + ## File structure -| Folder | Description | -| ------------------- | ----------- | +| Folder | Description | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data | Irradiance data for simulation, imported from <br> [NREL Solar Radiation Research Laboratory](https://midcdmz.nrel.gov/apps/sitehome.pl?site=BMS) (outdoor solar) <br> and [EnHANTs](https://enhants.ee.columbia.edu/indoor-irradiance-meas) dataset (indoor light) | -| finegrain | The finegrain model | -| hibernus_validation | A [TI Code Composer Studio](https://www.ti.com/tool/CCSTUDIO) (CCS) project folder of <br> an adapted version of *Hibernus* for validating results | -| model | The theoretical model | +| finegrain | The finegrain model as described in Section III-C of the paper, <br>with test programs | +| hibernus_validation | A [TI Code Composer Studio](https://www.ti.com/tool/CCSTUDIO) (CCS) project folder of <br> an adapted version of *Hibernus* for validating results | +| model | The theoretical model as described in Section III-B of the paper, <br>with test programs | ## Usage - The CCS project is developed upon MSP430FR6989, can be directly imported to CCS. -- For usage of the two models, please see README in each subfolder. \ No newline at end of file +- For usage of the two models, please see README files in each [model](https://git.soton.ac.uk/energy-driven/energy-storage-sizing/-/tree/master/model) and [finegrain](https://git.soton.ac.uk/energy-driven/energy-storage-sizing/-/tree/master/finegrain) subfolders. \ No newline at end of file diff --git a/hibernus_validation/hibernus/config.h b/hibernus_validation/hibernus/config.h deleted file mode 100755 index 2754ae3..0000000 --- a/hibernus_validation/hibernus/config.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - - -#endif diff --git a/hibernus_validation/hibernus/hibernus.c b/hibernus_validation/hibernus/hibernus.c index 612e9aa..b5722a4 100755 --- a/hibernus_validation/hibernus/hibernus.c +++ b/hibernus_validation/hibernus/hibernus.c @@ -1,3 +1,10 @@ +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT + */ + #include <hibernus/hibernus.h> #include <msp430.h> diff --git a/hibernus_validation/hibernus/hibernus.h b/hibernus_validation/hibernus/hibernus.h index f20cea5..3a240d7 100755 --- a/hibernus_validation/hibernus/hibernus.h +++ b/hibernus_validation/hibernus/hibernus.h @@ -1,23 +1,10 @@ /* -Hibernus for MSP430FR5739: + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT + */ -Hibernus: Software-based approach to intelligently hibernate and restore the system's state -in response to a power failure. This software exploits an external comparator. - -Citation: If you are using this code for your research please cite: - -[1] D. Balsamo, A. S. Weddell, G. V. Merrett, B. M. Al-Hashimi, D. Brunelli and L. Benini, - "Hibernus: Sustaining Computation During Intermittent Supply for Energy-Harvesting Systems," - in IEEE Embedded Systems Letters, vol. 7, no. 1, pp. 15-18, March 2015. - -[2] D. Balsamo; A. Weddell; A. Das; A. Arreola; D. Brunelli; B. Al-Hashimi; G. Merrett; L. Benini, - "Hibernus++: A Self-Calibrating and Adaptive System for Transiently-Powered Embedded Devices," - in IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems , vol.PP, no.99, pp.1-1 - -This research has been supported by the University of Southampton and the University of Bologna. -Copyright 2016, Domenico Balsamo, All rights reserved. -25/05/2016 -*/ #ifndef HIBERNATION_SRC #define HIBERNATION_SRC diff --git a/model/LICENSE b/model/LICENSE new file mode 100644 index 0000000..aefe5f3 --- /dev/null +++ b/model/LICENSE @@ -0,0 +1,23 @@ +MIT License + +Copyright (c) 2019-2021, University of Southampton and Contributors. +All rights reserved. + +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 (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +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. \ No newline at end of file diff --git a/model/Makefile b/model/Makefile index c6f1c5c..016c211 100644 --- a/model/Makefile +++ b/model/Makefile @@ -7,7 +7,6 @@ OUT_DIR = bin/ all : output_directory \ $(OUT_DIR)stor_constcurrent \ $(OUT_DIR)harv_stor \ - $(OUT_DIR)show_period \ $(OUT_DIR)rs_to_ram \ $(OUT_DIR)harv_stor_tradeoff \ $(OUT_DIR)harv_stor_range \ @@ -30,9 +29,6 @@ $(OUT_DIR)stor_constcurrent : stor_constcurrent.c model.o $(OUT_DIR)harv_stor : harv_stor.c model.o $(CC) $^ $(CFLAGS) -o $@ -$(OUT_DIR)show_period : show_period.c model.o - $(CC) $^ $(CFLAGS) -o $@ - $(OUT_DIR)rs_to_ram : rs_to_ram.c model.o $(CC) $^ $(CFLAGS) -o $@ diff --git a/model/README.md b/model/README.md index dcf9fa7..b108384 100644 --- a/model/README.md +++ b/model/README.md @@ -1,31 +1,73 @@ -<!-- # Explanation of each c file +# Introduction -## Current folder: -1. msp_hiber.c: capacitor sizing test based on MSP430 MCU - and Hibernus transient approach. +# Build and run -2. size_harv_stor.c: scaling energy harvester (pv cell area) - and energy storage capacity (capacitor capacitance) - together, using equation to speed up forward progress - estimation. +In the current ```model``` folder, simply enter: +```bash +make +``` +This builds all executables to the ```bin``` folder. -3. size_harvester.c: similar to 7, but scale energy - harvester only. +To run an executable: +```bash +cd bin/ +./<executable_name> +``` -4. size_storage.c: similar to 7, but scale energy storage - only. +For example: +```bash +cd bin/ +./stor_constcurrent +``` -5. sizemodel.c: time-based simulation model with adaptive - time step. +# Usage -## 'tests' folder: +## stor_constcurrent -6. countline.c: line counter test program for counting - the number of data lines in order to obtain the data time - length. +This is a program that outputs forward progress against supply current and energy storage capacitance, as well as maximum forward progress that can be achieved with each supply current. +The progrom prompts user input for the test ranges of capacitance and supply current. +For example: +``` +Please enter c_min c_step c_no (int int int, 'uF'): +7 1 93 +Please enter i_min i_step i_no (double double int, 'mA'): +0.1 0.1 3 +``` +This will test 7-99 uF capacitance and 0.1-0.9 mA supply current. -7. pv_model.c: PV cell model test program. +## rs_to_ram +The file name 'rs_to_ram' is short for 'Restore/Save Time Overheads scaled by RAM usage'. +This program explores the impact of different restore/save time overheads. +Restore/save time overheads should be linear to the state size. + +## harv_stor + +This program estimates forward progress under real-world energy conditions (irradiance) by sorting the energy conditions into a time ratio distribution (as opposed to a finegrain simulation process). +It scales the solar panel size and energy storage capacitance to gain a spectrum of forward progress. +Before running the program, please check Line 32 and 112 of the source file (harv_stor.c) for a correct reading format of your data file, and modify it when needed. +It prompts the uses for a data file of energy conditions, and test ranges of solar panel sizes and capacitance. +An example can be: +``` +bin/harv_stor +Please enter the filename and path of dataset: +../data/2018denver.txt +Please enter S_min S_max S_step (area PER CELL (mm^2), 4 cells total): +10 30 10 +Please enter c_min c_max c_step (uF, integer): +7 100 1 +``` + +## harv_stor_tradeoff, harv_stor_range, harv_stor_division, harv_stor_compare + +Developed upon __harv_stor__, these four programs share a similar usage with __harv_stor__ but is adapted for their own features. + +- harv_stor_tradeoff: This trades off between forward progress against capacitor volume and interruption periods in a cost function. The parameters of the cost function can be set in the source code. + +- harv_stor_range: This displays the percentiles of forward progress over the test range, rather than an average value. By default, it shows the 60th and 90th percentiles. + +- harv_stor_division: This processes the energy condition data in a 'division' base, i.e. produce forward progress for each division rather than the whole set of data. An example usage could be analysing daily/hourly forward progress over a year. + +- harv_stor_compare: This program explores, when given a certain PV panel area, how much the 'benefit' is by sizing energy storage capacitance. The 'benefit' is reflected on two things: 1) the improvement of forward progress when using the same PV panel area; 2) the reduction of PV panel area to achieve the same level of forward progress. -8. test.c: test program that actually you can write anything. --> \ No newline at end of file diff --git a/model/costfunction.c b/model/costfunction.c index 3c5df44..932424a 100644 --- a/model/costfunction.c +++ b/model/costfunction.c @@ -1,10 +1,8 @@ -/* - ****************************** - * costfunction.c - * function: a exploring test of cost functions - * usage: - * output: .csv in 'results' folders - ****************************** +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT */ @@ -19,17 +17,17 @@ #define ENHANTSD -#ifdef NREL// for NREL +#ifdef NREL // for NREL #define SLOT_NUMBER 1300 #define SLOT_UNIT 1.0 #endif -#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 +#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.001 -#endif +#endif -#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 +#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.005 #endif @@ -47,84 +45,79 @@ double cost_function(double fwpg, double cap); /* * Input: "data.csv" as an argument */ -int main (int argv, char** argc) -{ +int main(int argv, char** argc) { // general variables - double g; // irradiance - double cap; // capacitance + double g; // irradiance + double cap; // capacitance double v_ave; double g_ave; double thrp_sec_ave; double thrp_sec_ave_min; - double metric; + double metric; // test range parameters - int c_min, c_max, c_step; // energy storage test range - double cell_area; // area per cell + int c_min, c_max, c_step; // energy storage test range + double cell_area; // area per cell // arrays - int slot; // free slot index - unsigned long g_distrib[SLOT_NUMBER]; // number of slots - double t_ratio[SLOT_NUMBER]; // time ratio in each slot + int slot; // free slot index + unsigned long g_distrib[SLOT_NUMBER]; // number of slots + double t_ratio[SLOT_NUMBER]; // time ratio in each slot double i_harvest[SLOT_NUMBER]; double thrp_sec[SLOT_NUMBER]; - for (slot = 0; slot < SLOT_NUMBER; slot++) g_distrib[slot] = 0; // init g_distrib + for (slot = 0; slot < SLOT_NUMBER; slot++) + g_distrib[slot] = 0; // init g_distrib - // data reading variables - unsigned long int data_number = 0; // for recording data volume (number of csv lines) - char line[MAX_CHARACTER_PER_LINE]; + // data reading variables + unsigned long int data_number = 0; // for recording data volume (number of csv lines) + char line[MAX_CHARACTER_PER_LINE]; char* delete; - char delims[] = " ,"; + char delims[] = " ,"; // file pointers FILE* fp_g = NULL; FILE* fp_w = NULL; // open data file to read -#ifdef _WIN64 - if (fopen_s(&fp_g, argc[1], "r") != 0) { -#elif __APPLE__ if ((fp_g = fopen(argc[1], "r")) == NULL) { -#endif perror("Fail to read file"); return EXIT_FAILURE; } // open result file to write -#ifdef _WIN64 - if (fopen_s(&fp_w, "results\\costfunction.csv", "w") != 0) { -#elif __APPLE__ if ((fp_w = fopen("results/costfunction.csv", "w")) == NULL) { -#endif printf("Failed to write file.\n"); return EXIT_FAILURE; } - // Sort out irradiance distribution + // Sort out irradiance distribution while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g)) { // !!! the following three lines should be modified according to data file format delete = strtok(line, delims); #ifdef NREL delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL #endif - g = atof(strtok(NULL, delims)); // read irradiance + g = atof(strtok(NULL, delims)); // read irradiance if (g != g) { // g = NAN // print("NaN exist in dataset, please check.\n"); - } - else { + } else { #if defined ENHANTSA || defined ENHANTSD - g *= 1e-2; // uncomment for EnHANTs, comment for NREL + g *= 1e-2; // uncomment for EnHANTs, comment for NREL #endif data_number++; - if (g < 0) slot = 0; - else if (g >= SLOT_NUMBER * SLOT_UNIT) slot = SLOT_NUMBER - 1; - else slot = (int) (g / SLOT_UNIT); + if (g < 0) + slot = 0; + else if (g >= SLOT_NUMBER * SLOT_UNIT) + slot = SLOT_NUMBER - 1; + else + slot = (int) (g / SLOT_UNIT); g_distrib[slot]++; } } // printf("slot: value:\n"); - // for (slot = 0; slot < SLOT_NUMBER; slot++) printf("%10d %lu\n", slot, g_distrib[slot]); + // for (slot = 0; slot < SLOT_NUMBER; slot++) + // printf("%10d %lu\n", slot, g_distrib[slot]); for (slot = 0; slot < SLOT_NUMBER; slot++) { t_ratio[slot] = (double) (g_distrib[slot]) / data_number; } @@ -132,7 +125,7 @@ int main (int argv, char** argc) - // loop beginning for sizing harvester + // loop beginning for sizing harvester // input from terminal printf("Please enter cell area (area PER CELL and unit mm^2): "); scanf("%lf", &cell_area); @@ -145,10 +138,11 @@ int main (int argv, char** argc) - v_ave = (V_R + V_S) / 2; // voltage for switch mode + v_ave = (V_R + V_S) / 2; // voltage for switch mode /* ------ Sort out Iharvest distribution ------ */ for (slot = 0; slot < SLOT_NUMBER; slot++) { - g_ave = (slot + 0.5) * SLOT_UNIT; // take the medium of a slot as the mean g + // take the medium of a slot as the mean g + g_ave = (slot + 0.5) * SLOT_UNIT; i_harvest[slot] = pvCellCurrent(g_ave, v_ave, cell_area); } @@ -157,8 +151,8 @@ int main (int argv, char** argc) // code identical with sizing storage loop for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -180,13 +174,12 @@ int main (int argv, char** argc) /* ------ loop beginning for sizing storage ------ */ for (int i = c_min; i <= c_max; i += c_step) { - - cap = i * 1e-6; // c = i uF + cap = i * 1e-6; // c = i uF for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -204,7 +197,6 @@ int main (int argv, char** argc) // output printf("%lf, %d, %lf, %lf, %e\n", N_S * cell_area, i, thrp_sec_ave, thrp_sec_ave / thrp_sec_ave_min - 1, metric); fprintf(fp_w, "%lf, %d, %lf, %lf, %e\n", N_S * cell_area, i, thrp_sec_ave, thrp_sec_ave / thrp_sec_ave_min - 1, metric); - } /* ------ loop end for sizing storage ------ */ fclose(fp_g); @@ -212,27 +204,23 @@ int main (int argv, char** argc) return 0; } -double cost_function(double fwpg, double cap) -{ +double cost_function(double fwpg, double cap) { double metric; - // metric = pow(fwpg, W1) / + // metric = pow(fwpg, W1) / // pow(cap_volume(cap), W2) / - // pow(recharge_time(cap), W3); + // pow(recharge_time(cap), W3); - metric = fwpg / 0.2 - pow(cap_volume(cap) / 200.0, 2) - pow(recharge_time(cap), 2); - - return metric; + metric = fwpg / 0.2 - pow(cap_volume(cap) / 200.0, 2) - pow(recharge_time(cap), 2); + return metric; } -double cap_volume(double cap) -{ +double cap_volume(double cap) { return (double) 2.172 * pow(cap * 1e6, 0.685); } -double recharge_time(double cap) -{ +double recharge_time(double cap) { double current_supply = 0.5e-3; return ((cap * (V_R - V_S) + T_SAVE * (current_supply - I_S)) / (current_supply - I_SLEEP) + T_RESTORE); } \ No newline at end of file diff --git a/model/harv_stor.c b/model/harv_stor.c index e176467..e7ba919 100644 --- a/model/harv_stor.c +++ b/model/harv_stor.c @@ -1,15 +1,26 @@ +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT + */ + /* - ****************************** harv_stor.c function: scale solar panel size and storage capacitance to gain a spectrum of forward progress usage: - 1. modify constants and file reading code to suit dataset - 2. run executable with dataset filename as argument, e.g. - windows: harv_stor.exe data\2018denver.txt - unix: ./harv_stor.exe data/2018denver.txt + 1. modify constants and file reading code to suit dataset + see Line 32 and Line 112 + 2. run executable and configure in prompts, e.g. (in /model path) + bin/harv_stor + Please enter the filename and path of dataset: + ../data/2018denver.txt + Please enter S_min S_max S_step (area PER CELL (mm^2), 4 cells total): + 10 30 10 + Please enter c_min c_max c_step (uF, integer): + 7 100 1 output: .csv in 'results' folders - ****************************** */ @@ -24,32 +35,29 @@ // #define ENHANTSD -#ifdef NREL// for NREL +#ifdef NREL // for NREL #define SLOT_NUMBER 1300 #define SLOT_UNIT 1.0 #endif -#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 +#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.001 -#endif +#endif -#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 +#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.005 #endif -// #define PRINT_T_MODES // print t_off, t_switch, t_on, comment if no need +// #define PRINT_T_MODES // print t_off, t_switch, t_on, comment if no need -/* - * Input: "data.csv" as an argument - */ -int main (int argv, char** argc) -{ + +int main(int argv, char** argc) { // general variables - double g; // irradiance - double cap; // capacitance + double g; // irradiance + double cap; // capacitance double v_ave; double g_ave; double thrp_sec_avr; @@ -58,23 +66,24 @@ int main (int argv, char** argc) double t_on; // test range parameters - int c_min, c_max, c_step; // energy storage test range - double s_min, s_max, s_step; // area (surface, S) of energy harvester test range - double cell_area; // area per cell + int c_min, c_max, c_step; // energy storage test range + double s_min, s_max, s_step; // area (surface, S) of energy harvester test range + double cell_area; // area per cell // arrays - int slot; // free slot index - unsigned long g_distrib[SLOT_NUMBER]; // number of slots - double t_ratio[SLOT_NUMBER]; // time ratio in each slot + int slot; // free slot index + unsigned long g_distrib[SLOT_NUMBER]; // number of slots + double t_ratio[SLOT_NUMBER]; // time ratio in each slot double i_harvest[SLOT_NUMBER]; double thrp_sec[SLOT_NUMBER]; - for (slot = 0; slot < SLOT_NUMBER; slot++) g_distrib[slot] = 0; // init g_distrib + for (slot = 0; slot < SLOT_NUMBER; slot++) + g_distrib[slot] = 0; // init g_distrib - // data reading variables - unsigned long int data_number = 0; // for recording data volume (number of csv lines) - char line[MAX_CHARACTER_PER_LINE]; + // data reading variables + unsigned long int data_number = 0; // data volume (number of csv lines) + char line[MAX_CHARACTER_PER_LINE]; char* delete; - char delims[] = " ,"; + char delims[] = " ,"; // file pointers FILE* fp_g = NULL; @@ -83,56 +92,50 @@ int main (int argv, char** argc) char* filename = (char*) calloc(0x80, sizeof(char)); printf("Please enter the filename and path of dataset: \n"); fgets(filename, 0x80, stdin); - if (filename[strlen(filename) - 1] == '\n') + if (filename[strlen(filename) - 1] == '\n') filename[strlen(filename) - 1] = '\0'; // open data file to read -#ifdef _WIN64 - if (fopen_s(&fp_g, filename, "r") != 0) { -#elif __APPLE__ if ((fp_g = fopen(filename, "r")) == NULL) { -#endif perror("Fail to read file"); - return EXIT_FAILURE; } // open result file to write -#ifdef _WIN64 - if (fopen_s(&fp_w, "results\\harv_stor.csv", "w") != 0) { -#elif __APPLE__ - if ((fp_w = fopen("results/harv_stor.csv", "w")) == NULL) { -#endif + if ((fp_w = fopen("harv_stor.csv", "w")) == NULL) { printf("Failed to write file.\n"); return EXIT_FAILURE; } - // Sort out irradiance distribution + // Sort out irradiance distribution + // !!!the following block should be modified according to your data file format!!! while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g)) { - // !!! the following three lines should be modified according to data file format delete = strtok(line, delims); #ifdef NREL delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL #endif - g = atof(strtok(NULL, delims)); // read irradiance + g = atof(strtok(NULL, delims)); // read irradiance if (g != g) { // g = NAN // print("NaN exist in dataset, please check.\n"); - } - else { + } else { #if defined ENHANTSA || defined ENHANTSD - g *= 1e-2; // uncomment for EnHANTs, comment for NREL + g *= 1e-2; // uncomment for EnHANTs, comment for NREL #endif data_number++; - if (g < 0) slot = 0; - else if (g >= SLOT_NUMBER * SLOT_UNIT) slot = SLOT_NUMBER - 1; - else slot = (int) (g / SLOT_UNIT); + if (g < 0) + slot = 0; + else if (g >= SLOT_NUMBER * SLOT_UNIT) + slot = SLOT_NUMBER - 1; + else + slot = (int) (g / SLOT_UNIT); g_distrib[slot]++; } } // printf("slot: value:\n"); - // for (slot = 0; slot < SLOT_NUMBER; slot++) printf("%10d %lu\n", slot, g_distrib[slot]); + // for (slot = 0; slot < SLOT_NUMBER; slot++) + // printf("%10d %lu\n", slot, g_distrib[slot]); for (slot = 0; slot < SLOT_NUMBER; slot++) { t_ratio[slot] = (double) (g_distrib[slot]) / data_number; @@ -141,29 +144,30 @@ int main (int argv, char** argc) - // loop beginning for sizing harvester + // loop beginning for sizing harvester // input from terminal - printf("Please enter S_min S_max S_step (area PER CELL (mm^2), %d cells total): ", N_S); + printf("Please enter S_min S_max S_step (area PER CELL (mm^2), %d cells total):\n", N_S); scanf("%lf %lf %lf", &s_min, &s_max, &s_step); - printf("Please enter c_min c_max c_step (uF, integer): "); + printf("Please enter c_min c_max c_step (uF, integer):\n"); scanf("%d %d %d", &c_min, &c_max, &c_step); // output to terminal and file #ifdef PRINT_T_MODES printf("S_panel(mm^2), Cap(uF), Avg Thrp/Sec, t_on, t_switch, t_off\n"); fprintf(fp_w, "S_panel(mm^2), Cap(uF), Avg Thrp/Sec, t_on, t_switch, t_off\n"); -#else +#else printf("S_panel(mm^2), Cap(uF), Avg Thrp/Sec\n"); fprintf(fp_w, "S_panel(mm^2), Cap(uF), Avg Thrp/Sec\n"); -#endif // PRINT_T_MODES +#endif // PRINT_T_MODES - v_ave = (V_R + V_S) / 2; // voltage for switch mode + v_ave = (V_R + V_S) / 2; // voltage for switch mode /* ------ loop beginning for sizing harvester ------ */ for (cell_area = s_min; cell_area <= s_max; cell_area += s_step) { /* ------ Sort out Iharvest distribution ------ */ for (slot = 0; slot < SLOT_NUMBER; slot++) { - g_ave = (slot + 0.5) * SLOT_UNIT; // take the medium of a slot as the mean g + // take the medium of a slot as the mean g + g_ave = (slot + 0.5) * SLOT_UNIT; i_harvest[slot] = pvCellCurrent(g_ave, v_ave, cell_area); } @@ -172,8 +176,8 @@ int main (int argv, char** argc) // code identical with sizing storage loop for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -186,32 +190,38 @@ int main (int argv, char** argc) t_on = 0.0; for (slot = 0; slot < SLOT_NUMBER; slot++) { #ifdef PRINT_T_MODES - if (thrp_sec[slot] >= 1.0) t_on += t_ratio[slot]; - else if (thrp_sec[slot] <= 0.0) t_off += t_ratio[slot]; - else t_switch += t_ratio[slot]; -#endif // PRINT_T_MODES + if (thrp_sec[slot] >= 1.0) + t_on += t_ratio[slot]; + else if (thrp_sec[slot] <= 0.0) + t_off += t_ratio[slot]; + else + t_switch += t_ratio[slot]; +#endif // PRINT_T_MODES thrp_sec_avr += t_ratio[slot] * thrp_sec[slot]; } // output #ifdef PRINT_T_MODES - printf("%lf, %lf, %lf, %lf, %lf, %lf\n", N_S * cell_area, cap * 1e6, thrp_sec_avr, t_on, t_switch, t_off); - fprintf(fp_w, "%lf, %lf, %lf, %lf, %lf, %lf\n", N_S * cell_area, cap * 1e6, thrp_sec_avr, t_on, t_switch, t_off); -#else - printf("%lf, %lf, %lf\n", N_S * cell_area, cap * 1e6, thrp_sec_avr); - fprintf(fp_w, "%lf, %lf, %lf\n", N_S * cell_area, cap * 1e6, thrp_sec_avr); -#endif // PRINT_T_MODES + printf("%lf, %lf, %lf, %lf, %lf, %lf\n", + N_S * cell_area, cap * 1e6, thrp_sec_avr, t_on, t_switch, t_off); + fprintf(fp_w, "%lf, %lf, %lf, %lf, %lf, %lf\n", + N_S * cell_area, cap * 1e6, thrp_sec_avr, t_on, t_switch, t_off); +#else + printf("%lf, %lf, %lf\n", + N_S * cell_area, cap * 1e6, thrp_sec_avr); + fprintf(fp_w, "%lf, %lf, %lf\n", + N_S * cell_area, cap * 1e6, thrp_sec_avr); +#endif // PRINT_T_MODES /* ------ loop beginning for sizing storage ------ */ for (int i = c_min; i <= c_max; i += c_step) { - - cap = i * 1e-6; // c = i uF + cap = i * 1e-6; // c = i uF for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -225,27 +235,36 @@ int main (int argv, char** argc) t_on = 0.0; for (slot = 0; slot < SLOT_NUMBER; slot++) { #ifdef PRINT_T_MODES - if (thrp_sec[slot] >= 1.0) t_on += t_ratio[slot]; - else if (thrp_sec[slot] <= 0.0) t_off += t_ratio[slot]; - else t_switch += t_ratio[slot]; -#endif // PRINT_T_MODES + if (thrp_sec[slot] >= 1.0) + t_on += t_ratio[slot]; + else if (thrp_sec[slot] <= 0.0) + t_off += t_ratio[slot]; + else + t_switch += t_ratio[slot]; +#endif // PRINT_T_MODES thrp_sec_avr += t_ratio[slot] * thrp_sec[slot]; } // output #ifdef PRINT_T_MODES - printf("%lf, %d, %lf, %lf, %lf, %lf\n", N_S * cell_area, i, thrp_sec_avr, t_on, t_switch, t_off); - fprintf(fp_w, "%lf, %d, %lf, %lf, %lf, %lf\n", N_S * cell_area, i, thrp_sec_avr, t_on, t_switch, t_off); -#else - printf("%lf, %d, %lf\n", N_S * cell_area, i, thrp_sec_avr); - fprintf(fp_w, "%lf, %d, %lf\n", N_S * cell_area, i, thrp_sec_avr); -#endif // PRINT_T_MODES - - } /* ------ loop end for sizing storage ------ */ - } /* ------ loop end for sizing harvester ------ */ + printf("%lf, %d, %lf, %lf, %lf, %lf\n", + N_S * cell_area, i, thrp_sec_avr, t_on, t_switch, t_off); + fprintf(fp_w, "%lf, %d, %lf, %lf, %lf, %lf\n", + N_S * cell_area, i, thrp_sec_avr, t_on, t_switch, t_off); +#else + printf("%lf, %d, %lf\n", + N_S * cell_area, i, thrp_sec_avr); + fprintf(fp_w, "%lf, %d, %lf\n", + N_S * cell_area, i, thrp_sec_avr); +#endif // PRINT_T_MODES + } /* ------ loop end for sizing storage ------ */ + } /* ------ loop end for sizing harvester ------ */ fclose(fp_g); fclose(fp_w); + + printf("\nSee results in 'harv_stor.csv'.\n"); + return 0; -} \ No newline at end of file +} diff --git a/model/harv_stor_compare.c b/model/harv_stor_compare.c index 6586fd8..39dafe5 100644 --- a/model/harv_stor_compare.c +++ b/model/harv_stor_compare.c @@ -1,15 +1,8 @@ -/* - ****************************** - harv_stor.c - function: scale solar panel size and storage capacitance - to gain a spectrum of forward progress - usage: - 1. modify constants and file reading code to suit dataset - 2. run executable with dataset filename as argument, e.g. - windows: harv_stor.exe data\2018denver.txt - unix: ./harv_stor.exe data/2018denver.txt - output: .csv in 'results' folders - ****************************** +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT */ @@ -24,17 +17,17 @@ // #define ENHANTSD -#ifdef NREL// for NREL +#ifdef NREL // for NREL #define SLOT_NUMBER 1300 #define SLOT_UNIT 1.0 #endif -#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 +#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.001 -#endif +#endif -#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 +#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.005 #endif @@ -42,95 +35,86 @@ // #define PRINT_T_MODES // print t_off, t_switch, t_on, comment if no need -/* - * Input: "data.csv" as an argument - */ -int main (int argv, char** argc) -{ + +int main(int argv, char** argc) { // general variables - double g; // irradiance - double cap; // capacitance + double g; // irradiance + double cap; // capacitance double v_ave; double g_ave; double thrp_sec_avr; // test range parameters - int c_min, c_max, c_step; // energy storage test range - double s_comp, s_step; // area (surface, S) of energy harvester test range - double cell_area; // area per cell + int c_min, c_max, c_step; // energy storage test range + double s_comp, s_step; // area (surface, S) of energy harvester test range + double cell_area; // area per cell // arrays - int slot; // free slot index - unsigned long g_distrib[SLOT_NUMBER]; // number of slots - double t_ratio[SLOT_NUMBER]; // time ratio in each slot + int slot; // free slot index + unsigned long g_distrib[SLOT_NUMBER]; // number of slots + double t_ratio[SLOT_NUMBER]; // time ratio in each slot double i_harvest[SLOT_NUMBER]; double thrp_sec[SLOT_NUMBER]; - for (slot = 0; slot < SLOT_NUMBER; slot++) g_distrib[slot] = 0; // init g_distrib + for (slot = 0; slot < SLOT_NUMBER; slot++) + g_distrib[slot] = 0; // init g_distrib - // data reading variables - unsigned long int data_number = 0; // for recording data volume (number of csv lines) - char line[MAX_CHARACTER_PER_LINE]; + // data reading variables + unsigned long int data_number = 0; // for recording data volume (number of csv lines) + char line[MAX_CHARACTER_PER_LINE]; char* delete; - char delims[] = " ,"; + char delims[] = " ,"; // file pointers FILE* fp_g = NULL; - FILE* fp_w = NULL; + // FILE* fp_w = NULL; char* filename = (char*) calloc(0x80, sizeof(char)); printf("Please enter the filename and path of dataset: \n"); fgets(filename, 0x80, stdin); - if (filename[strlen(filename) - 1] == '\n') + if (filename[strlen(filename) - 1] == '\n') filename[strlen(filename) - 1] = '\0'; // open data file to read -#ifdef _WIN64 - if (fopen_s(&fp_g, filename, "r") != 0) { -#elif __APPLE__ if ((fp_g = fopen(filename, "r")) == NULL) { -#endif perror("Fail to read file"); - return EXIT_FAILURE; } // open result file to write -#ifdef _WIN64 - if (fopen_s(&fp_w, "results\\harv_stor_compare.csv", "w") != 0) { -#elif __APPLE__ - if ((fp_w = fopen("results/harv_stor_compare.csv", "w")) == NULL) { -#endif - printf("Failed to write file.\n"); - return EXIT_FAILURE; - } + // if ((fp_w = fopen("results/harv_stor_compare.csv", "w")) == NULL) { + // printf("Failed to write file.\n"); + // return EXIT_FAILURE; + // } - // Sort out irradiance distribution + // Sort out irradiance distribution + // !!!the following block should be modified according to your data file format!!! while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g)) { - // !!! the following three lines should be modified according to data file format delete = strtok(line, delims); #ifdef NREL delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL #endif - g = atof(strtok(NULL, delims)); // read irradiance + g = atof(strtok(NULL, delims)); // read irradiance if (g != g) { // g = NAN // print("NaN exist in dataset, please check.\n"); - } - else { + } else { #if defined ENHANTSA || defined ENHANTSD - g *= 1e-2; // uncomment for EnHANTs, comment for NREL + g *= 1e-2; // uncomment for EnHANTs, comment for NREL #endif data_number++; - if (g < 0) slot = 0; - else if (g >= SLOT_NUMBER * SLOT_UNIT) slot = SLOT_NUMBER - 1; - else slot = (int) (g / SLOT_UNIT); + if (g < 0) + slot = 0; + else if (g >= SLOT_NUMBER * SLOT_UNIT) + slot = SLOT_NUMBER - 1; + else + slot = (int) (g / SLOT_UNIT); g_distrib[slot]++; } - } // printf("slot: value:\n"); - // for (slot = 0; slot < SLOT_NUMBER; slot++) printf("%10d %lu\n", slot, g_distrib[slot]); + // for (slot = 0; slot < SLOT_NUMBER; slot++) + // printf("%10d %lu\n", slot, g_distrib[slot]); for (slot = 0; slot < SLOT_NUMBER; slot++) { t_ratio[slot] = (double) (g_distrib[slot]) / data_number; @@ -139,11 +123,11 @@ int main (int argv, char** argc) - // loop beginning for sizing harvester + // loop beginning for sizing harvester // input from terminal - printf("Please enter s_comp s_step (area PER CELL (mm^2), %d cells total): ", N_S); + printf("Please enter s_comp s_step (area PER CELL (mm^2), %d cells total):\n", N_S); scanf("%lf %lf", &s_comp, &s_step); - printf("Please enter c_min c_max c_step (uF, integer): "); + printf("Please enter c_min c_max c_step (uF, integer):\n"); scanf("%d %d %d", &c_min, &c_max, &c_step); // output to terminal and file // printf("S_panel(mm^2), Cap(uF), Avg Thrp/Sec\n"); @@ -151,21 +135,19 @@ int main (int argv, char** argc) - v_ave = (V_R + V_S) / 2; // voltage for switch mode - - - + v_ave = (V_R + V_S) / 2; // voltage for switch mode // test improvement of sizing energy storage at s_comp for (slot = 0; slot < SLOT_NUMBER; slot++) { - g_ave = (slot + 0.5) * SLOT_UNIT; // take the medium of a slot as the mean g + // take the medium of a slot as the mean g + g_ave = (slot + 0.5) * SLOT_UNIT; i_harvest[slot] = pvCellCurrent(g_ave, v_ave, s_comp); } cap = minCap(); for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -175,17 +157,18 @@ int main (int argv, char** argc) thrp_sec_avr += t_ratio[slot] * thrp_sec[slot]; } double thrp_sec_avr_min = thrp_sec_avr; + printf("\nOriginal setting (using minimum capacitance):\n"); + printf("PV panel area (mm^2), Capacitance (uF), Forward progress\n"); printf("%lf, %lf, %lf\n", N_S * s_comp, cap * 1e6, thrp_sec_avr_min); double c_opt = cap; double thrp_sec_avr_opt = thrp_sec_avr_min; /* ------ loop beginning for sizing storage ------ */ - for (int i = c_min; i <= c_max; i += c_step) { - cap = i * 1e-6; // c = i uF + cap = i * 1e-6; // c = i uF for (slot = 0; slot < SLOT_NUMBER; slot++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking + // error checking if (thrp_sec[slot] < 0.0) thrp_sec[slot] = 0.0; } // statistics @@ -197,8 +180,12 @@ int main (int argv, char** argc) thrp_sec_avr_opt = thrp_sec_avr; c_opt = cap; } - } /* ------ loop end for sizing storage ------ */ - printf("%lf, %lf, %lf, %lf\n", N_S * s_comp, c_opt * 1e6, thrp_sec_avr_opt, thrp_sec_avr_opt / thrp_sec_avr_min - 1); + } /* ------ loop end for sizing storage ------ */ + printf("\nUse optimal capacitance with the same PV panel area:\n"); + printf("PV panel area (mm^2), Capacitance (uF), Forward progress, Improvement\n"); + printf("%lf, %lf, %lf, %lf\n", + N_S * s_comp, c_opt * 1e6, thrp_sec_avr_opt, + thrp_sec_avr_opt / thrp_sec_avr_min - 1); @@ -206,17 +193,18 @@ int main (int argv, char** argc) /* ------ loop beginning for sizing harvester ------ */ cell_area = s_comp; - uint16_t cnt = 0xFF; + uint16_t cnt = 0xFF; while (cnt >= 0) { /* ------ Sort out Iharvest distribution ------ */ for (slot = 0; slot < SLOT_NUMBER; slot++) { - g_ave = (slot + 0.5) * SLOT_UNIT; // take the medium of a slot as the mean g + // take the medium of a slot as the mean g + g_ave = (slot + 0.5) * SLOT_UNIT; i_harvest[slot] = pvCellCurrent(g_ave, v_ave, cell_area); } /* ------ loop beginning for sizing storage ------ */ for (int i = c_min; i <= c_max; i += c_step) { - cap = i * 1e-6; // c = i uF + cap = i * 1e-6; // c = i uF for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); if (thrp_sec[slot] < 0.0) thrp_sec[slot] = 0.0; @@ -243,11 +231,13 @@ int main (int argv, char** argc) cell_area += s_step; if (cnt >=0) { - printf("%lf, %lf\n", cell_area * N_S, c_opt * 1e6); + printf("\nAlternative setting to achieve the same forward progress:\n"); + printf("PV panel area (mm^2), Capacitance (uF), Forward progress\n"); + printf("%lf, %lf, %lf\n", cell_area * N_S, c_opt * 1e6, thrp_sec_avr_opt); } - fclose(fp_g); - fclose(fp_w); + // fclose(fp_w); + return 0; -} \ No newline at end of file +} diff --git a/model/harv_stor_division.c b/model/harv_stor_division.c index 568c607..7b2e88d 100644 --- a/model/harv_stor_division.c +++ b/model/harv_stor_division.c @@ -1,15 +1,8 @@ -/* - ****************************** - harv_stor_division.c - function: estimate total forward progress with divisions, - scale storage capacitance - usage: - 1. modify constants and file-reading code to suit dataset - 2. run executable with dataset filename as an argument, e.g. - windows: harv_stor_division.exe data\2018denver.txt - unix: ./harv_stor_division.exe data/2018denver.txt - output: .csv in 'results' folders - +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT */ @@ -20,83 +13,76 @@ /* ---------- Constants --------- */ // for NREL -// #define SLOT_NUMBER 1300 -// #define SLOT_UNIT 1.0 +#define SLOT_NUMBER 1300 +#define SLOT_UNIT 1.0 // for EnHANTs A, < 10 W/m^2 // #define SLOT_NUMBER 5000 // #define SLOT_UNIT 0.001 -// for EnHANTs D, < 25 W/m^2 -#define SLOT_NUMBER 5000 -#define SLOT_UNIT 0.005 - -const int N_DATA_DIV = 2880; // no. of data per division +// // for EnHANTs D, < 25 W/m^2 +// #define SLOT_NUMBER 5000 +// #define SLOT_UNIT 0.005 +const int N_DATA_DIV = 2880; // no. of data per division -/* - * Input: "*.csv" (your .csv dataset filename) as an argument - */ -int main (int argv, char** argc) -{ +int main(int argv, char** argc) { // general variables - double g; // irradiance - double cap; // capacitance + double g; // irradiance + double cap; // capacitance double v_ave; double g_ave; double thrp_sec_total; // test range parameters - int c_max; // energy storage test range - // double s_panel; // test range of solar panel area (surface, S) - double cell_area; // area per cell + int c_max; // energy storage test range + // double s_panel; // test range of solar panel area (surface, S) + double cell_area; // area per cell // arrays - int slot; // free slot index - unsigned long g_distrib[SLOT_NUMBER]; // number of slots - double t_ratio[SLOT_NUMBER]; // time ratio in each slot + int slot; // free slot index + unsigned long g_distrib[SLOT_NUMBER]; // number of slots + double t_ratio[SLOT_NUMBER]; // time ratio in each slot double i_harvest[SLOT_NUMBER]; double thrp_sec[SLOT_NUMBER]; - // data reading variables - unsigned long int data_number = 0; // for recording data volume (number of csv lines) - char line[MAX_CHARACTER_PER_LINE]; + // data reading variables + unsigned long int data_number = 0; // for recording data volume (number of csv lines) + char line[MAX_CHARACTER_PER_LINE]; char* delete; - char delims[] = " ,"; + char delims[] = " ,"; // file pointers FILE* fp_g = NULL; FILE* fp_w = NULL; + + char* filename = (char*) calloc(0x80, sizeof(char)); + printf("Please enter the filename and path of dataset: \n"); + fgets(filename, 0x80, stdin); + if (filename[strlen(filename) - 1] == '\n') + filename[strlen(filename) - 1] = '\0'; + // open data file to read -#ifdef _WIN64 - if (fopen_s(&fp_g, argc[1], "r") != 0) { -#elif __APPLE__ - if ((fp_g = fopen(argc[1], "r")) == NULL) { -#endif + if ((fp_g = fopen(filename, "r")) == NULL) { perror("Fail to read file"); return EXIT_FAILURE; } // open result file to write -#ifdef _WIN64 - if (fopen_s(&fp_w, "results\\harv_stor_division.csv", "w") != 0) { -#elif __APPLE__ - if ((fp_w = fopen("results/harv_stor.csv", "w")) == NULL) { -#endif + if ((fp_w = fopen("harv_stor_division.csv", "w")) == NULL) { printf("Failed to write file.\n"); return EXIT_FAILURE; } - // count lines + // count lines + // !!!the following block should be modified according to your data file format!!! while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g)) { - // !!! the following three lines should be modified according to data file format delete = strtok(line, delims); - // delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL - g = atof(strtok(NULL, delims)); // read irradiance - if (g != g) { // when g = NaN, get rid of this data + delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL + g = atof(strtok(NULL, delims)); // read irradiance + if (g != g) { // when g = NaN, get rid of this data // print("NaN exist in dataset, please check.\n"); - } - else { + } else { // g *= 1e-2; // uncomment for EnHANTs, comment for NREL data_number++; } @@ -104,19 +90,20 @@ int main (int argv, char** argc) rewind(fp_g); printf("total no. of data lines: %lu\n", data_number); printf("no. of data lines per division: %d\n", N_DATA_DIV); - unsigned int n_div = data_number / N_DATA_DIV ; + unsigned int n_div = data_number / N_DATA_DIV; printf("no. of divisions: %u\n", n_div); - printf("no. of data lines of the last division (ignored): %lu\n", data_number % N_DATA_DIV); + printf("no. of data lines of the last division (ignored): %lu\n", + data_number % N_DATA_DIV); double* thrp_sec_ave; thrp_sec_ave = calloc(n_div, sizeof(double)); - // loop beginning for sizing harvester + // loop beginning for sizing harvester // input from terminal - printf("Please enter cell_area (area PER CELL and unit mm^2, 4 cells in series): "); + printf("Please enter cell_area (area PER CELL and unit mm^2, 4 cells in series):\n"); scanf("%lf", &cell_area); printf("solar panel area: %lf\n", cell_area * N_S); - printf("Please enter c_max (uF, integer): "); + printf("Please enter c_max (uF, integer):\n"); scanf("%d", &c_max); // output headers to file @@ -127,15 +114,15 @@ int main (int argv, char** argc) - v_ave = (V_R + V_S) / 2; // voltage for switch mode + v_ave = (V_R + V_S) / 2; // voltage for switch mode /* ------ MinCap Test for Comparison ------ */ // cap = minCap(); // // code identical with sizing storage loop // for (slot = 0; slot < SLOT_NUMBER; slot ++) { // thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // // error checking - // if (thrp_sec[slot] < 0.0) { + // // error checking + // if (thrp_sec[slot] < 0.0) { // printf("Storage not enough.\n"); // return EXIT_FAILURE; // } @@ -157,43 +144,48 @@ int main (int argv, char** argc) /* ------ loop beginning for sizing storage ------ */ - for (cap = 0.1 * 1e-6; cap <= c_max * 1e-6; - cap += (cap * 1e6 < (int) ceil(minCap() * 1e6)) ? 0.1 * 1e-6 : 1e-6) { - + for (cap = 0.1 * 1e-6; cap <= c_max * 1e-6; + cap += (cap * 1e6 < (int) ceil(minCap() * 1e6)) ? 1e-7 : 1e-6) { thrp_sec_total = 0.0; // output cap (uF) fprintf(fp_w, "%.1lf, ", cap * 1e6); - // Sort out irradiance distribution - for (int j = 0; j < n_div; j++) { // omit the last division - int count; - count = 0; - for (slot = 0; slot < SLOT_NUMBER; slot++) g_distrib[slot] = 0; // init g_distrib - while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g) + // Sort out irradiance distribution + for (int j = 0; j < n_div; j++) { // omit the last division + int count = 0; + for (slot = 0; slot < SLOT_NUMBER; slot++) + g_distrib[slot] = 0; // init g_distrib + + // !!!the following block should be modified according to your data file format!!! + while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g) && count < N_DATA_DIV) { // !!! the following three lines should be modified according to data file format delete = strtok(line, delims); - // delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL - g = atof(strtok(NULL, delims)); // read irradiance - if (g != g) { // when g = NaN, get rid of this data + delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL + g = atof(strtok(NULL, delims)); // read irradiance + if (g != g) { // when g = NaN, get rid of this data // print("NaN exist in dataset, please check.\n"); - } - else { - g *= 1e-2; // uncomment for EnHANTs, comment for NREL - if (g < 0) slot = 0; // negative readings treated as zero - else if (g >= SLOT_NUMBER * SLOT_UNIT) slot = SLOT_NUMBER - 1; - else slot = (int) (g / SLOT_UNIT); + } else { + // g *= 1e-2; // uncomment for EnHANTs, comment for NREL + if (g < 0) + slot = 0; // negative readings treated as zero + else if (g >= SLOT_NUMBER * SLOT_UNIT) + slot = SLOT_NUMBER - 1; + else + slot = (int) (g / SLOT_UNIT); g_distrib[slot]++; } count++; } + // t_ratio[] for (slot = 0; slot < SLOT_NUMBER; slot++) { t_ratio[slot] = (double) g_distrib[slot] / N_DATA_DIV; } // i_harvest[] for (slot = 0; slot < SLOT_NUMBER; slot++) { - g_ave = (slot + 0.5) * SLOT_UNIT; // take the half of a slot as the mean g + // take the half of a slot as the mean g + g_ave = (slot + 0.5) * SLOT_UNIT; i_harvest[slot] = pvCellCurrent(g_ave, v_ave, cell_area); } // thrp_sec[] @@ -214,10 +206,11 @@ int main (int argv, char** argc) // output thrp fprintf(fp_w, "%lf\n", thrp_sec_total); rewind(fp_g); - } /* ------ loop end for sizing storage ------ */ fclose(fp_g); fclose(fp_w); + + printf("\nSee results in 'harv_stor_division.csv'.\n"); return 0; -} \ No newline at end of file +} diff --git a/model/harv_stor_range.c b/model/harv_stor_range.c index 4fb7ce2..6acfc3a 100644 --- a/model/harv_stor_range.c +++ b/model/harv_stor_range.c @@ -1,15 +1,8 @@ -/* - ****************************** - harv_stor.c - function: scale solar panel size and storage capacitance - to gain a spectrum of forward progress - usage: - 1. modify constants and file reading code to suit dataset - 2. run executable with dataset filename as argument, e.g. - windows: harv_stor.exe data\2018denver.txt - unix: ./harv_stor.exe data/2018denver.txt - output: .csv in 'results' folders - ****************************** +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT */ @@ -24,32 +17,29 @@ // #define ENHANTSD -#ifdef NREL// for NREL +#ifdef NREL // for NREL #define SLOT_NUMBER 1300 #define SLOT_UNIT 1.0 #endif -#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 +#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.001 -#endif +#endif -#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 +#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.005 #endif -#define PRINT_T_MODES // print t_off, t_switch, t_on, comment if no need +#define PRINT_T_MODES // print t_off, t_switch, t_on, comment if no need -/* - * Input: "data.csv" as an argument - */ -int main (int argv, char** argc) -{ + +int main(int argv, char** argc) { // general variables - double g; // irradiance - double cap; // capacitance + double g; // irradiance + double cap; // capacitance double v_ave; double g_ave; double thrp_sec_avr; @@ -60,23 +50,24 @@ int main (int argv, char** argc) double t_on; // test range parameters - int c_min, c_max, c_step; // energy storage test range - // double s_min, s_max, s_step; // area (surface, S) of energy harvester test range - double cell_area; // area per cell + int c_min, c_max, c_step; // energy storage test range + // double s_min, s_max, s_step; // area (surface, S) of energy harvester test range + double cell_area; // area per cell // arrays - int slot; // free slot index - unsigned long g_distrib[SLOT_NUMBER]; // number of slots - double t_ratio[SLOT_NUMBER]; // time ratio in each slot + int slot; // free slot index + unsigned long g_distrib[SLOT_NUMBER]; // number of slots + double t_ratio[SLOT_NUMBER]; // time ratio in each slot double i_harvest[SLOT_NUMBER]; double thrp_sec[SLOT_NUMBER]; - for (slot = 0; slot < SLOT_NUMBER; slot++) g_distrib[slot] = 0; // init g_distrib + for (slot = 0; slot < SLOT_NUMBER; slot++) + g_distrib[slot] = 0; // init g_distrib - // data reading variables - unsigned long int data_number = 0; // for recording data volume (number of csv lines) - char line[MAX_CHARACTER_PER_LINE]; + // data reading variables + unsigned long int data_number = 0; // for recording data volume (number of csv lines) + char line[MAX_CHARACTER_PER_LINE]; char* delete; - char delims[] = " ,"; + char delims[] = " ,"; // file pointers FILE* fp_g = NULL; @@ -85,57 +76,50 @@ int main (int argv, char** argc) char* filename = (char*) calloc(0x80, sizeof(char)); printf("Please enter the filename and path of dataset: \n"); fgets(filename, 0x80, stdin); - if (filename[strlen(filename) - 1] == '\n') + if (filename[strlen(filename) - 1] == '\n') filename[strlen(filename) - 1] = '\0'; // open data file to read -#ifdef _WIN64 - if (fopen_s(&fp_g, filename, "r") != 0) { -#elif __APPLE__ if ((fp_g = fopen(filename, "r")) == NULL) { -#endif perror("Fail to read file"); - return EXIT_FAILURE; } // open result file to write -#ifdef _WIN64 - if (fopen_s(&fp_w, "results\\harv_stor_range.csv", "w") != 0) { -#elif __APPLE__ if ((fp_w = fopen("results/harv_stor_range.csv", "w")) == NULL) { -#endif printf("Failed to write file.\n"); return EXIT_FAILURE; } - // Sort out irradiance distribution + // Sort out irradiance distribution + // !!!the following block should be modified according to your data file format!!! while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g)) { - // !!! the following three lines should be modified according to data file format delete = strtok(line, delims); #ifdef NREL delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL #endif - g = atof(strtok(NULL, delims)); // read irradiance + g = atof(strtok(NULL, delims)); // read irradiance if (g != g) { // g = NAN // print("NaN exist in dataset, please check.\n"); - } - else { + } else { #if defined ENHANTSA || defined ENHANTSD - g *= 1e-2; // uncomment for EnHANTs, comment for NREL + g *= 1e-2; // uncomment for EnHANTs, comment for NREL #endif data_number++; - if (g < 0) slot = 0; - else if (g >= SLOT_NUMBER * SLOT_UNIT) slot = SLOT_NUMBER - 1; - else slot = (int) (g / SLOT_UNIT); + if (g < 0) + slot = 0; + else if (g >= SLOT_NUMBER * SLOT_UNIT) + slot = SLOT_NUMBER - 1; + else + slot = (int) (g / SLOT_UNIT); g_distrib[slot]++; } - } // printf("slot: value:\n"); - // for (slot = 0; slot < SLOT_NUMBER; slot++) printf("%10d %lu\n", slot, g_distrib[slot]); + // for (slot = 0; slot < SLOT_NUMBER; slot++) + // printf("%10d %lu\n", slot, g_distrib[slot]); for (slot = 0; slot < SLOT_NUMBER; slot++) { t_ratio[slot] = (double) (g_distrib[slot]) / data_number; @@ -144,7 +128,7 @@ int main (int argv, char** argc) - // loop beginning for sizing harvester + // loop beginning for sizing harvester // input from terminal // printf("Please enter S_min S_max S_step (area PER CELL (mm^2), %d cells total): ", N_S); // scanf("%lf %lf %lf", &s_min, &s_max, &s_step); @@ -159,10 +143,11 @@ int main (int argv, char** argc) - v_ave = (V_R + V_S) / 2; // voltage for switch mode + v_ave = (V_R + V_S) / 2; // voltage for switch mode /* ------ Sort out Iharvest distribution ------ */ for (slot = 0; slot < SLOT_NUMBER; slot++) { - g_ave = (slot + 0.5) * SLOT_UNIT; // take the medium of a slot as the mean g + // take the medium of a slot as the mean g + g_ave = (slot + 0.5) * SLOT_UNIT; i_harvest[slot] = pvCellCurrent(g_ave, v_ave, cell_area); } @@ -171,8 +156,8 @@ int main (int argv, char** argc) // code identical with sizing storage loop for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -185,10 +170,13 @@ int main (int argv, char** argc) t_on = 0.0; for (slot = 0; slot < SLOT_NUMBER; slot++) { #ifdef PRINT_T_MODES - if (thrp_sec[slot] >= 1.0) t_on += t_ratio[slot]; - else if (thrp_sec[slot] <= 0.0) t_off += t_ratio[slot]; - else t_switch += t_ratio[slot]; -#endif // PRINT_T_MODES + if (thrp_sec[slot] >= 1.0) + t_on += t_ratio[slot]; + else if (thrp_sec[slot] <= 0.0) + t_off += t_ratio[slot]; + else + t_switch += t_ratio[slot]; +#endif // PRINT_T_MODES thrp_sec_avr += t_ratio[slot] * thrp_sec[slot]; } @@ -216,33 +204,32 @@ int main (int argv, char** argc) // output #ifdef PRINT_T_MODES - printf("%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf\n", - N_S * cell_area, cap * 1e6, - thrp_sec_avr, - thrp_sec_60, - thrp_sec_90, - t_off, t_switch, t_on); - fprintf(fp_w, "%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf\n", - N_S * cell_area, cap * 1e6, - thrp_sec_avr, - thrp_sec_60, - thrp_sec_90, - t_off, t_switch, t_on); -#else + printf("%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf\n", + N_S * cell_area, cap * 1e6, + thrp_sec_avr, + thrp_sec_60, + thrp_sec_90, + t_off, t_switch, t_on); + fprintf(fp_w, "%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf\n", + N_S * cell_area, cap * 1e6, + thrp_sec_avr, + thrp_sec_60, + thrp_sec_90, + t_off, t_switch, t_on); +#else printf("%lf, %lf, %lf\n", N_S * cell_area, cap * 1e6, thrp_sec_avr); fprintf(fp_w, "%lf, %lf, %lf\n", N_S * cell_area, cap * 1e6, thrp_sec_avr); -#endif // PRINT_T_MODES +#endif // PRINT_T_MODES /* ------ loop beginning for sizing storage ------ */ for (int i = c_min; i <= c_max; i += c_step) { - - cap = i * 1e-6; // c = i uF + cap = i * 1e-6; // c = i uF for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -256,10 +243,13 @@ int main (int argv, char** argc) t_on = 0.0; for (slot = 0; slot < SLOT_NUMBER; slot++) { #ifdef PRINT_T_MODES - if (thrp_sec[slot] >= 1.0) t_on += t_ratio[slot]; - else if (thrp_sec[slot] <= 0.0) t_off += t_ratio[slot]; - else t_switch += t_ratio[slot]; -#endif // PRINT_T_MODES + if (thrp_sec[slot] >= 1.0) + t_on += t_ratio[slot]; + else if (thrp_sec[slot] <= 0.0) + t_off += t_ratio[slot]; + else + t_switch += t_ratio[slot]; +#endif // PRINT_T_MODES thrp_sec_avr += t_ratio[slot] * thrp_sec[slot]; } @@ -287,26 +277,25 @@ int main (int argv, char** argc) // output #ifdef PRINT_T_MODES - printf("%lf, %d, %lf, %lf, %lf, %lf, %lf, %lf\n", - N_S * cell_area, i, - thrp_sec_avr, - thrp_sec_60, - thrp_sec_90, - t_off, t_switch, t_on); - fprintf(fp_w, "%lf, %d, %lf, %lf, %lf, %lf, %lf, %lf\n", - N_S * cell_area, i, - thrp_sec_avr, - thrp_sec_60, - thrp_sec_90, - t_off, t_switch, t_on); -#else + printf("%lf, %d, %lf, %lf, %lf, %lf, %lf, %lf\n", + N_S * cell_area, i, + thrp_sec_avr, + thrp_sec_60, + thrp_sec_90, + t_off, t_switch, t_on); + fprintf(fp_w, "%lf, %d, %lf, %lf, %lf, %lf, %lf, %lf\n", + N_S * cell_area, i, + thrp_sec_avr, + thrp_sec_60, + thrp_sec_90, + t_off, t_switch, t_on); +#else printf("%lf, %d, %lf\n", N_S * cell_area, i, thrp_sec_avr); fprintf(fp_w, "%lf, %d, %lf\n", N_S * cell_area, i, thrp_sec_avr); -#endif // PRINT_T_MODES - +#endif // PRINT_T_MODES } /* ------ loop end for sizing storage ------ */ fclose(fp_g); fclose(fp_w); return 0; -} \ No newline at end of file +} diff --git a/model/harv_stor_tradeoff.c b/model/harv_stor_tradeoff.c index b83dc95..72b6875 100644 --- a/model/harv_stor_tradeoff.c +++ b/model/harv_stor_tradeoff.c @@ -1,11 +1,8 @@ -/* - ****************************** - harv_stor_tradeoff.c - usage: - windows: harv_stor.exe data\2018denver.txt - unix: ./harv_stor.exe data/2018denver.txt - output: .csv in 'results' folders - ****************************** +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT */ @@ -20,17 +17,17 @@ // #define ENHANTSD -#ifdef NREL// for NREL +#ifdef NREL // for NREL #define SLOT_NUMBER 1300 - #define SLOT_UNIT 1.0 + #define SLOT_UNIT 1.0 #endif -#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 +#ifdef ENHANTSA // for EnHANTs A, < 5 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.001 -#endif +#endif -#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 +#ifdef ENHANTSD // for EnHANTs D, < 25 W/m^2 #define SLOT_NUMBER 5000 #define SLOT_UNIT 0.005 #endif @@ -44,21 +41,20 @@ double cost_function(double fwpg, double cap); -int main (int argv, char** argc) -{ +int main(int argv, char** argc) { // general variables - double g; // irradiance - double cap; // capacitance + double g; // irradiance + double cap; // capacitance double v_ave; double g_ave; double fwpg; - double metric; - double metric_max; // for recording the maximum cost function metric + double metric; + double metric_max; // for recording the maximum cost function metric // test range parameters - int c_min, c_max, c_step; // energy storage test range - double s_min, s_max, s_step; // area (surface, S) of energy harvester test range - double cell_area; // area per cell + int c_min, c_max, c_step; // energy storage test range + double s_min, s_max, s_step; // area (surface, S) of energy harvester test range + double cell_area; // area per cell // compared variables double cap_min, cap_opt, cap_max; @@ -67,18 +63,19 @@ int main (int argv, char** argc) double t_recharge_min, t_recharge_opt, t_recharge_max; // arrays - int slot; // free slot index - unsigned long g_distrib[SLOT_NUMBER]; // number of g in each slot - double t_ratio[SLOT_NUMBER]; // time ratio in each slot + int slot; // free slot index + unsigned long g_distrib[SLOT_NUMBER]; // number of g in each slot + double t_ratio[SLOT_NUMBER]; // time ratio in each slot double i_harvest[SLOT_NUMBER]; double thrp_sec[SLOT_NUMBER]; - for (slot = 0; slot < SLOT_NUMBER; slot++) g_distrib[slot] = 0; // init g_distrib + for (slot = 0; slot < SLOT_NUMBER; slot++) + g_distrib[slot] = 0; // init g_distrib - // data reading variables - unsigned long int data_number = 0; // for recording data volume (number of csv lines) - char line[MAX_CHARACTER_PER_LINE]; + // data reading variables + unsigned long int data_number = 0; // data volume (number of csv lines) + char line[MAX_CHARACTER_PER_LINE]; char* delete; - char delims[] = " ,"; + char delims[] = " ,"; // file pointers FILE* fp_g = NULL; @@ -87,56 +84,50 @@ int main (int argv, char** argc) char* filename = (char*) calloc(0x80, sizeof(char)); printf("Please enter the filename and path of dataset: \n"); fgets(filename, 0x80, stdin); - if (filename[strlen(filename) - 1] == '\n') + if (filename[strlen(filename) - 1] == '\n') filename[strlen(filename) - 1] = '\0'; // open data file to read -#ifdef _WIN64 - if (fopen_s(&fp_g, filename, "r") != 0) { -#elif __APPLE__ if ((fp_g = fopen(filename, "r")) == NULL) { -#endif perror("Fail to read file"); - return EXIT_FAILURE; } // open result file to write -#ifdef _WIN64 - if (fopen_s(&fp_w, "results\\harv_stor_tradeoff.csv", "w") != 0) { -#elif __APPLE__ - if ((fp_w = fopen("results/harv_stor_tradeoff.csv", "w")) == NULL) { -#endif + if ((fp_w = fopen("harv_stor_tradeoff.csv", "w")) == NULL) { printf("Failed to write file.\n"); return EXIT_FAILURE; } - // Sort out irradiance distribution + // Sort out irradiance distribution + // !!!the following block should be modified according to your data file format!!! while (fgets(line, MAX_CHARACTER_PER_LINE, fp_g)) { - // !!! the following three lines should be modified according to data file format delete = strtok(line, delims); #ifdef NREL delete = strtok(NULL, delims); // comment this line for EnHANTs, uncomment for NREL #endif - g = atof(strtok(NULL, delims)); // read irradiance + g = atof(strtok(NULL, delims)); // read irradiance if (g != g) { // g = NAN // print("NaN exist in dataset, please check.\n"); - } - else { + } else { #if defined ENHANTSA || defined ENHANTSD - g *= 1e-2; // uncomment for EnHANTs, comment for NREL + g *= 1e-2; // uncomment for EnHANTs, comment for NREL #endif data_number++; - if (g < 0) slot = 0; - else if (g >= SLOT_NUMBER * SLOT_UNIT) slot = SLOT_NUMBER - 1; - else slot = (int) (g / SLOT_UNIT); + if (g < 0) + slot = 0; + else if (g >= SLOT_NUMBER * SLOT_UNIT) + slot = SLOT_NUMBER - 1; + else + slot = (int) (g / SLOT_UNIT); g_distrib[slot]++; } } // printf("slot: value:\n"); - // for (slot = 0; slot < SLOT_NUMBER; slot++) printf("%10d %lu\n", slot, g_distrib[slot]); + // for (slot = 0; slot < SLOT_NUMBER; slot++) + // printf("%10d %lu\n", slot, g_distrib[slot]); for (slot = 0; slot < SLOT_NUMBER; slot++) { t_ratio[slot] = (double) (g_distrib[slot]) / data_number; @@ -146,9 +137,9 @@ int main (int argv, char** argc) // input from terminal - printf("Please enter S_min S_max S_step (area PER CELL (mm^2), %d cells total): ", N_S); + printf("Please enter S_min S_max S_step (area PER CELL (mm^2), %d cells total):\n", N_S); scanf("%lf %lf %lf", &s_min, &s_max, &s_step); - printf("Please enter c_min c_max c_step (uF, integer): "); + printf("Please enter c_min c_max c_step (uF, integer):\n"); scanf("%d %d %d", &c_min, &c_max, &c_step); // output to terminal and file @@ -167,13 +158,13 @@ int main (int argv, char** argc) - v_ave = (V_R + V_S) / 2; // voltage for switch mode + v_ave = (V_R + V_S) / 2; // voltage for switch mode /* ------ loop beginning for sizing harvester ------ */ for (cell_area = s_min; cell_area <= s_max; cell_area += s_step) { - /* ------ Sort out Iharvest distribution ------ */ for (slot = 0; slot < SLOT_NUMBER; slot++) { - g_ave = (slot + 0.5) * SLOT_UNIT; // take the medium of a slot as the mean g + // take the medium of a slot as the mean g + g_ave = (slot + 0.5) * SLOT_UNIT; i_harvest[slot] = pvCellCurrent(g_ave, v_ave, cell_area); } @@ -183,8 +174,8 @@ int main (int argv, char** argc) // code identical with sizing storage loop for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -202,13 +193,12 @@ int main (int argv, char** argc) // metric_max = cost_function(fwpg_min, cap_min); metric_max = 0.0; for (int i = c_min; i <= c_max; i += c_step) { - - cap = i * 1e-6; // c = i uF + cap = i * 1e-6; // c = i uF for (slot = 0; slot < SLOT_NUMBER; slot ++) { thrp_sec[slot] = onTimeRatio(i_harvest[slot], cap); - // error checking - if (thrp_sec[slot] < 0.0) { + // error checking + if (thrp_sec[slot] < 0.0) { printf("Storage not enough.\n"); return EXIT_FAILURE; } @@ -228,7 +218,7 @@ int main (int argv, char** argc) cap_opt = cap; } if (fwpg > fwpg_max) { - fwpg_max = fwpg; + fwpg_max = fwpg; cap_max = cap; } } /* ------ loop end for sizing storage ------ */ @@ -239,43 +229,43 @@ int main (int argv, char** argc) t_recharge_min = recharge_time(cap_min); t_recharge_opt = recharge_time(cap_opt); t_recharge_max = recharge_time(cap_max); - fprintf(fp_w, "%.2lf, ", N_S * cell_area); - fprintf(fp_w, "%.2lf, %.2lf, %.2lf, ", cap_min * 1e6, cap_opt * 1e6, cap_max * 1e6); + fprintf(fp_w, "%.2lf, %.2lf, %.2lf, ", + cap_min * 1e6, cap_opt * 1e6, cap_max * 1e6); // printf("%lf\n", metric_max); - fprintf(fp_w, "%lf, %lf, %lf, %lf, ", fwpg_min, fwpg_opt, fwpg_max, fwpg_opt/fwpg_max); - fprintf(fp_w, "%lf, %lf, %lf, ", capvol_min, capvol_opt, capvol_max); - fprintf(fp_w, "%lf, %lf, %lf\n", t_recharge_min, t_recharge_opt, t_recharge_max); - + fprintf(fp_w, "%lf, %lf, %lf, %lf, ", + fwpg_min, fwpg_opt, fwpg_max, fwpg_opt/fwpg_max); + fprintf(fp_w, "%lf, %lf, %lf, ", + capvol_min, capvol_opt, capvol_max); + fprintf(fp_w, "%lf, %lf, %lf\n", + t_recharge_min, t_recharge_opt, t_recharge_max); } /* ------ loop end for sizing harvester ------ */ fclose(fp_g); fclose(fp_w); + printf("\nSee results in 'harv_stor_tradeoff.csv'.\n"); + return 0; } -double cost_function(double fwpg, double cap) -{ +double cost_function(double fwpg, double cap) { double metric; - // metric = pow(fwpg, W1) / + // metric = pow(fwpg, W1) / // pow(cap_volume(cap), W2) / - // pow(recharge_time(cap), W3); + // pow(recharge_time(cap), W3); - metric = fwpg / 0.2 - pow(cap_volume(cap) / 200.0, 2) - pow(recharge_time(cap), 2); - - return metric; + metric = fwpg / 0.2 - pow(cap_volume(cap) / 200.0, 2) - pow(recharge_time(cap), 2); + return metric; } -double cap_volume(double cap) -{ +double cap_volume(double cap) { return (double) 2.172 * pow(cap * 1e6, 0.685); } -double recharge_time(double cap) -{ +double recharge_time(double cap) { double current_supply = 0.5e-3; return ((cap * (V_R - V_S) + T_SAVE * (current_supply - I_S)) / (current_supply - I_SLEEP) + T_RESTORE); -} \ No newline at end of file +} diff --git a/model/model.c b/model/model.c index c4bd32b..d6f1be2 100644 --- a/model/model.c +++ b/model/model.c @@ -1,28 +1,36 @@ +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT + */ + #include "model.h" // args: irradiance g (W/m^2), operating voltage v (V), cell_area (mm^2) // return: harvested current (A) -double pvCellCurrent(double g, double v, double cell_area) -{ - if (v < 0){ +double pvCellCurrent(double g, double v, double cell_area) { + if (v < 0) { printf("PV cell voltage < 0! Abnormal. \n"); return EXIT_FAILURE; } - double Voc = V_OC_CELL * N_S; // V - double Isc = I_SC_MM2 * cell_area; // - double Vmpp = V_MPP_CELL * N_S; // Vmpp - double Impp = I_MPP_MM2 * cell_area; // Impp - double Gpu; // percentage irradiance - double i; + double Voc = V_OC_CELL * N_S; // V + double Isc = I_SC_MM2 * cell_area; + double Vmpp = V_MPP_CELL * N_S; // Vmpp + double Impp = I_MPP_MM2 * cell_area; // Impp + double Gpu; // percentage irradiance + double i; if (g < 0) g = 0; Gpu = g / G_REF; - if (v > Voc) i = 0; - else i = Gpu * Isc * (1 - exp(log(1 - Impp / Isc) * (v - Voc) / (Vmpp - Voc))); + if (v > Voc) + i = 0; + else + i = Gpu * Isc * (1 - exp(log(1 - Impp / Isc) + * (v - Voc) / (Vmpp - Voc))); return i; } -double capCurrentLeak(double cap) -{ +double capCurrentLeak(double cap) { double i_leak; // Aluminium @@ -31,53 +39,51 @@ double capCurrentLeak(double cap) // Tantalum AVX TAJ double v_ratio = ((V_R + V_S) / 2.0) / V_RATED_CAP; - double i_leak_ratio = I_LEAK_RATIO_START * pow(1 / I_LEAK_RATIO_START, v_ratio); + double i_leak_ratio = I_LEAK_RATIO_START + * pow(1 / I_LEAK_RATIO_START, v_ratio); i_leak = K_CAP_LEAK * cap * V_RATED_CAP * i_leak_ratio; - return i_leak; } -double onTimeRatio(double i_supply, double cap) -{ +double onTimeRatio(double i_supply, double cap) { double i_leak; - double i_in; // just for denoting i_harvest - i_leak + double i_in; // just for denoting i_harvest - i_leak double v_pr; double v_ps; double t_exe, t_charge; double t_period; - double t_exe_percent; // 0 ~ 1, ratio of actual active time to total time + double t_exe_percent; // 0 ~ 1, ratio of actual active time to total time i_leak = capCurrentLeak(cap); i_in = i_supply - i_leak; if (cap < minCapRisk(i_supply)) { - // printf("Energy insufficient (in worst case, Iin = 0) at Cap = %.0lfuF.\n" - // , cap * 1e6); - return -1.0; // a negative value to indicate insufficient storage - } + // printf("Energy insufficient (in worst case, Iin = 0) at Cap = %.0lfuF.\n", cap * 1e6); + return -1.0; // a negative value to indicate insufficient storage + } if (i_in < I_SLEEP) t_exe_percent = 0.0; else if (i_in > I_EXE) t_exe_percent = 1.0; else { #ifdef HIBERNUS - v_pr = V_R; // no restore after sleep + v_pr = V_R; // no restore after sleep #else v_pr = (i_in - I_R) * T_RESTORE / cap + V_R; -#endif // HIBERNUS +#endif // HIBERNUS v_ps = (i_in - I_S) * T_SAVE / cap + V_S; - + t_exe = cap * (v_pr - V_S) / (I_EXE - i_in); t_charge = cap * (V_R - v_ps) / (i_in - I_SLEEP); #ifdef HIBERNUS - t_period = t_exe + t_charge + T_SAVE; // no restore after sleep + t_period = t_exe + t_charge + T_SAVE; // no restore after sleep #else - t_period = t_exe + t_charge + T_SAVE + T_RESTORE; -#endif // HIBERNUS - + t_period = t_exe + t_charge + T_SAVE + T_RESTORE; +#endif // HIBERNUS + t_exe_percent = t_exe / t_period; } @@ -85,138 +91,137 @@ double onTimeRatio(double i_supply, double cap) } -double onTimeRatio_RS(double i_supply, double cap, double t_restore, double t_save) -{ +double onTimeRatio_RS(double i_supply, double cap, double t_restore, double t_save) { double i_leak; - double i_in; // just for denoting i_harvest - i_leak + double i_in; // just for denoting i_harvest - i_leak double v_pr; double v_ps; double t_exe, t_charge; double t_period; - double t_exe_percent; // 0 ~ 1, ratio of actual active time to total time + double t_exe_percent; // 0 ~ 1, ratio of actual active time to total time i_leak = capCurrentLeak(cap); i_in = i_supply - i_leak; if (cap < minCapRisk_RS(i_supply, t_restore, t_save)) { - // printf("Energy insufficient (in worst case, Iin = 0) at Cap = %.0lfuF.\n" - // , cap * 1e6); - return -1.0; // a negative value to indicate insufficient storage - } + // printf("Energy insufficient (in worst case, Iin = 0) at Cap = %.0lfuF.\n", cap * 1e6); + return -1.0; // a negative value to indicate insufficient storage + } if (i_in < I_SLEEP) t_exe_percent = 0.0; else if (i_in > I_EXE) t_exe_percent = 1.0; - else{ + else { #ifdef HIBERNUS - v_pr = V_R; // no restore after sleep + v_pr = V_R; // no restore after sleep #else v_pr = (i_in - I_R) * t_restore / cap + V_R; -#endif // HIBERNUS +#endif // HIBERNUS v_ps = (i_in - I_S) * t_save / cap + V_S; - + t_exe = cap * (v_pr - V_S) / (I_EXE - i_in); t_charge = cap * (V_R - v_ps) / (i_in - I_SLEEP); #ifdef HIBERNUS - t_period = t_exe + t_charge + t_save; // no restore after sleep + t_period = t_exe + t_charge + t_save; // no restore after sleep #else - t_period = t_exe + t_charge + t_save + t_restore; -#endif // HIBERNUS - + t_period = t_exe + t_charge + t_save + t_restore; +#endif // HIBERNUS + t_exe_percent = t_exe / t_period; } return t_exe_percent; } -double rsto_RS(double i_supply, double cap, double t_restore, double t_save) -{ +double rsto_RS(double i_supply, double cap, double t_restore, double t_save) { double i_leak; - double i_in; // just for denoting i_harvest - i_leak + double i_in; // just for denoting i_harvest - i_leak double v_pr; double v_ps; double t_exe, t_charge; double t_period; - double t_rs_percent; // 0 ~ 1, ratio of actual active time to total time + double t_rs_percent; // 0 ~ 1, ratio of actual active time to total time i_leak = capCurrentLeak(cap); i_in = i_supply - i_leak; if (cap < minCapRisk_RS(i_supply, t_restore, t_save)) { - // printf("Energy insufficient (in worst case, Iin = 0) at Cap = %.0lfuF.\n" - // , cap * 1e6); - return -1.0; // a negative value to indicate insufficient storage - } + // printf("Energy insufficient (in worst case, Iin = 0) at Cap = %.0lfuF.\n", cap * 1e6); + return -1.0; // a negative value to indicate insufficient storage + } if (i_in < I_SLEEP) t_rs_percent = -1.0; else if (i_in > I_EXE) t_rs_percent = -1.0; - else{ - + else { #ifdef HIBERNUS - v_pr = V_R; // no restore after sleep + v_pr = V_R; // no restore after sleep #else v_pr = (i_in - I_R) * t_restore / cap + V_R; -#endif // HIBERNUS +#endif // HIBERNUS v_ps = (i_in - I_S) * t_save / cap + V_S; - + t_exe = cap * (v_pr - V_S) / (I_EXE - i_in); t_charge = cap * (V_R - v_ps) / (i_in - I_SLEEP); #ifdef HIBERNUS - t_period = t_exe + t_charge + t_save; // no restore after sleep + t_period = t_exe + t_charge + t_save; // no restore after sleep #else - t_period = t_exe + t_charge + t_save + t_restore; -#endif // HIBERNUS - + t_period = t_exe + t_charge + t_save + t_restore; +#endif // HIBERNUS + t_rs_percent = (t_restore + t_save) / t_period; } return t_rs_percent; } // Safe min. cap -double minCap() -{ - double cap_r, cap_s; - cap_r = I_R * T_RESTORE / (V_R - V_S); +double minCap() { + double cap_r, cap_s; + cap_r = I_R * T_RESTORE / (V_R - V_S); cap_s = I_S * T_SAVE / (V_S - V_OFF); return (cap_r > cap_s) ? cap_r : cap_s; } -double minCap_RS(double t_restore, double t_save) -{ - double cap_r, cap_s; - cap_r = I_R * t_restore / (V_R - V_S); +double minCap_RS(double t_restore, double t_save) { + double cap_r, cap_s; + cap_r = I_R * t_restore / (V_R - V_S); cap_s = I_S * t_save / (V_S - V_OFF); return (cap_r > cap_s) ? cap_r : cap_s; } // Risky min. cap -double minCapRisk(double i_supply) -{ - double cap_r, cap_s; +double minCapRisk(double i_supply) { + double cap_r, cap_s; - if (i_supply > I_R) cap_r = 0; - else cap_r = (I_R - i_supply) * T_RESTORE / (V_R - V_S); + if (i_supply > I_R) + cap_r = 0; + else + cap_r = (I_R - i_supply) * T_RESTORE / (V_R - V_S); - if (i_supply > I_S) cap_s = 0; - else cap_s = (I_S - i_supply) * T_SAVE / (V_S - V_OFF); + if (i_supply > I_S) + cap_s = 0; + else + cap_s = (I_S - i_supply) * T_SAVE / (V_S - V_OFF); return (cap_r > cap_s) ? cap_r : cap_s; } -double minCapRisk_RS(double i_supply, double t_restore, double t_save) -{ - double cap_r, cap_s; +double minCapRisk_RS(double i_supply, double t_restore, double t_save) { + double cap_r, cap_s; - if (i_supply > I_R) cap_r = 0; - else cap_r = (I_R - i_supply) * t_restore / (V_R - V_S); + if (i_supply > I_R) + cap_r = 0; + else + cap_r = (I_R - i_supply) * t_restore / (V_R - V_S); - if (i_supply > I_S) cap_s = 0; - else cap_s = (I_S - i_supply) * t_save / (V_S - V_OFF); + if (i_supply > I_S) + cap_s = 0; + else + cap_s = (I_S - i_supply) * t_save / (V_S - V_OFF); return (cap_r > cap_s) ? cap_r : cap_s; } \ No newline at end of file diff --git a/model/model.h b/model/model.h index 272e969..a3ebd64 100644 --- a/model/model.h +++ b/model/model.h @@ -1,3 +1,10 @@ +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT + */ + #ifndef _MODEL_H #define _MODEL_H @@ -56,30 +63,30 @@ double rsto_RS(double i_supply, double cap, double t_restore, double t_save); // Reference: Panasonic Amorton Amorphous Silicon Solar Cells // Open-circuit voltage -#define V_OC_CELL 0.89 // 0.89 V per cell +#define V_OC_CELL 0.89 // 0.89 V per cell // Short-circuit current -#define I_SC_MM2 0.148e-3 // A/mm^2, (14.8 mA/cm^2) per cell -// Maximum power point voltage -#define V_MPP_CELL 0.65 // 0.65 V per cell +#define I_SC_MM2 0.148e-3 // A/mm^2, (14.8 mA/cm^2) per cell +// Maximum power point voltage +#define V_MPP_CELL 0.65 // 0.65 V per cell // Maximum power point current -#define I_MPP_MM2 0.121e-3 // A/mm^2, (12.1 mA/cm^2) per cell +#define I_MPP_MM2 0.121e-3 // A/mm^2, (12.1 mA/cm^2) per cell // Reference irradiance for the measurements above #define G_REF 1000.0 // No. of cells in series, to scale voltage -#define N_S 4 // to get a 3.56V Voc to match MCU max operating voltage 3.6V -// Default area per cell, to scale current -#define DEFAULT_CELL_AREA 10.0 // mm^2 default area of a cell +#define N_S 4 // to get a 3.56V Voc to match MCU max operating voltage 3.6V +// Default area per cell, to scale current +#define DEFAULT_CELL_AREA 10.0 // mm^2 default area of a cell // Not use no. of cell in parallel due to poor granularity -// #define N_P 1 // reserved +// #define N_P 1 // reserved // --------------------------------------- // Capacitor model parameters // Reference: AVX TAJ series, and "Low Leakage Current Aspect of Designing with // Tantalum and Niobium Oxide Capacitors" -#define V_RATED_CAP 10.0 // 10V rated voltage -#define K_CAP_LEAK 0.01 // for AVX TAJ tantalum, 0.01 +#define V_RATED_CAP 10.0 // 10V rated voltage +#define K_CAP_LEAK 0.01 // for AVX TAJ tantalum, 0.01 #define I_LEAK_RATIO_START 0.05 @@ -87,9 +94,9 @@ double rsto_RS(double i_supply, double cap, double t_restore, double t_save); // --------------------------------------- // Load model parameters, after 17 Oct 2019 // Experimentally measured data -// Experiment setup: +// Experiment setup: // Master Clock frequency 8 MHz -// 1.2V Vref module, +// 1.2V Vref module, // Internal comparator (w/ 3Mohms voltage divider), // Workload Dijkstra, // RAM usage 1696B. @@ -99,46 +106,46 @@ double rsto_RS(double i_supply, double cap, double t_restore, double t_save); // Sleep current draw #define I_SLEEP 26e-6 // A, 26uA @ 2.1 ~ 2.4V, measured 6 Dec 2019 -// #define I_SLEEP 27e-6 // A, 27uA -// #define I_SLEEP 10e-6 // A, 10uA demo -// #define I_SLEEP 400e-6 // A, 400uA ADC voltage polling +// #define I_SLEEP 27e-6 // A, 27uA +// #define I_SLEEP 10e-6 // A, 10uA demo +// #define I_SLEEP 400e-6 // A, 400uA ADC voltage polling // Execute current draw -#define I_EXE 887e-6 // A, 887uA @ 2.1 ~ 2.4V, measured 6 Dec 2019 -// #define I_EXE 895e-6 // A, 895uA Dijkstra +#define I_EXE 887e-6 // A, 887uA @ 2.1 ~ 2.4V, measured 6 Dec 2019 +// #define I_EXE 895e-6 // A, 895uA Dijkstra // Current mean 0.8957mA min 0.8330mA max 0.9260mA, Voltage 3.2882V // #define I_EXE 1e-3 // A, 1mA demo -// #define I_EXE 870e-6 // A, 870uA counting down (w/ ADC) +// #define I_EXE 870e-6 // A, 870uA counting down (w/ ADC) // Restore current draw -#define I_R 971e-6 // A, 971uA @ 2.4V, measured 6 Dec 2019 +#define I_R 971e-6 // A, 971uA @ 2.4V, measured 6 Dec 2019 // #define I_R 1020e-6 // A, 1020uA // #define I_R 1e-3 // A, same as I_EXE -// Save (hibernate) current draw -#define I_S 811e-6 // A, 811uA @ 2.1V, measured 6 Dec 2019 +// Save (hibernate) current draw +#define I_S 811e-6 // A, 811uA @ 2.1V, measured 6 Dec 2019 // #define I_S 902e-6 // A, 902uA // #define I_S 1e-3 // A, same as I_EXE -#define V_OFF 1.8 // V, ref: msp430fr6989 datasheet, Table 5-2 +#define V_OFF 1.8 // V, ref: msp430fr6989 datasheet, Table 5-2 // Restore threshold -#define V_R 2.4 // V, Comparator E, measured roughly +#define V_R 2.4 // V, Comparator E, measured roughly // #define V_R 2.3 // V, hibernus // Save threshold -#define V_S 2.1 // V, Comparator E, measured roughly +#define V_S 2.1 // V, Comparator E, measured roughly // #define V_S 2.2 // V, hibernate threshold // Restore/Save time overheads -#define T_RESTORE_MAX 2.298e-3 // second, full RAM 2048B -#define T_SAVE_MAX 2.274e-3 // second, full RAM 2048B -#define T_RESTORE_MIN 0.232e-3 // second, least RAM 160B stack -#define T_SAVE_MIN 0.208e-3 // second, least RAM 160B stack +#define T_RESTORE_MAX 2.298e-3 // second, full RAM 2048B +#define T_SAVE_MAX 2.274e-3 // second, full RAM 2048B +#define T_RESTORE_MIN 0.232e-3 // second, least RAM 160B stack +#define T_SAVE_MIN 0.208e-3 // second, least RAM 160B stack // #define T_RS_SCALE #ifdef T_RS_SCALE // if time overheads linearly scaled by RAM usage - #define RAM_USAGE_TUNE 1.0 // 0 ~ 1, scaling factor + #define RAM_USAGE_TUNE 1.0 // 0 ~ 1, scaling factor #define T_RESTORE (T_RESTORE_MIN + \ (T_RESTORE_MAX - \ T_RESTORE_MIN) * \ @@ -151,28 +158,28 @@ double rsto_RS(double i_supply, double cap, double t_restore, double t_save); // if given with a certain value #define T_RESTORE 1.903e-3 #define T_SAVE 1.880e-3 -#endif // T_RS_SCALE +#endif // T_RS_SCALE -// use clock frequency in the metric if needed -#define PERF_ACTIVE 8.0 // MHz -#define PERF_INACTIVE 0.0 // MHz +// use clock frequency in the metric if needed +#define PERF_ACTIVE 8.0 // MHz +#define PERF_INACTIVE 0.0 // MHz -#define HIBERNUS +#define HIBERNUS // if HIBERNUS, only restore after brownout, no restore after sleep // if not HIBERNUS, restore after brownout and sleep // --------------------------------------- // Old Parameters (obsolete) -// const double power[3] = {0.0, 1.10e-6, 2.79e-3}; // W, msp430fr6989, Hibernus++ +// const double power[3] = {0.0, 1.10e-6, 2.79e-3}; // W, msp430fr6989, Hibernus++ // const double perf [3] = {0.0, 0.0, 8.0}; // MHz // const double time_step = 0.005; -// const double V_OFF = 2.0; +// const double V_OFF = 2.0; // const double E_HIBERNATE = 2.99e-6; // Graceful; // const double E_RESTORE = 3.56e-6; // unit J // const double T_HIBERNATE = 1.40e-3; // unit second // const double T_RESTORE = 1.35e-3; -// const double APP_CYCLE = 0.1; // 0.1 million cycles to complete one FFT iteration, refer to slaa698b +// const double APP_CYCLE = 0.1; // 0.1 million cycles to complete one FFT iteration, refer to slaa698b // const double V_OC = 1.80; // const double I_SC = 0.275 / 3000.0; // const double V_M = 1.50; // given from datasheet diff --git a/model/rs_to_ram.c b/model/rs_to_ram.c index b270476..aeb309d 100644 --- a/model/rs_to_ram.c +++ b/model/rs_to_ram.c @@ -1,3 +1,11 @@ +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT + */ + + /* * rs_to_ram.c * (restore/save time overheads of RAM) @@ -13,14 +21,13 @@ #include "model.h" /* ----------- Macros ----------- */ -#define I_SUPPLY 0.4e-3 +#define I_SUPPLY 0.4e-3 /* ------ Global Variables ------ */ /* ------ Function Declare ------ */ /* ------------ Main ------------ */ -int main(int argv, char** argc) -{ - double scale_factor; +int main(int argv, char** argc) { + double scale_factor; double t_restore; double t_save; unsigned int test_num; @@ -29,20 +36,15 @@ int main(int argv, char** argc) double cap_min; double cap_opt; const double cap_step = 1e-6; - const double cap_max = 400e-6; + const double cap_max = 400e-6; double fwp_mincap; double fwp_optcap; double fwp_temp; - - FILE* fp1 = NULL; -#ifdef _WIN64 - if (fopen_s(&fp1, "results\\rs_to_ram.csv", "w") != 0) { -#elif __APPLE__ - if ((fp1 = fopen("results/rs_to_ram.csv", "w")) == NULL) { -#endif + + if ((fp1 = fopen("rs_to_ram.csv", "w")) == NULL) { printf("Failed to write file rs_to.csv.\n"); return 1; } @@ -52,18 +54,13 @@ int main(int argv, char** argc) printf("T_RESTORE_MIN: %.3lf ms, T_SAVE_MIN: %.3lf ms\n", T_RESTORE_MIN * 1e3, T_SAVE_MIN * 1e3); printf("T_RESTORE_MAX: %.3lf ms, T_SAVE_MAX: %.3lf ms\n", T_RESTORE_MAX * 1e3, T_SAVE_MAX * 1e3); printf("\nPlease enter No. of tests (divisions): "); - -#ifdef _WIN64 - scanf_s("%d", &test_num); -#elif __APPLE__ scanf("%d", &test_num); -#endif - + printf("\nFind optimal capacity with granularity %.2lf uF and below %.2lf uF...\n", cap_step * 1e6, cap_max * 1e6); fprintf(fp1, "ram usage, state size, fwp_opt, fwp_mincap, fwp_impr, opt_cap, min_cap, rsto reduction, fwp of opt_cap for min ram, fwp of opt_cap for max ram\n"); for (int i = 0; i <= (test_num - 1); i++) { - scale_factor = (double) i / (test_num - 1); + scale_factor = (double) i / (test_num - 1); t_restore = T_RESTORE_MIN + (T_RESTORE_MAX - T_RESTORE_MIN) * scale_factor; t_save = T_SAVE_MIN + (T_SAVE_MAX - T_SAVE_MIN) * scale_factor; @@ -80,27 +77,17 @@ int main(int argv, char** argc) cap_opt = cap; } } - fprintf(fp1, "%.3lf, %.1lf, %lf, %lf, %lf, %.3lf, %.3lf, %lf, %lf, %lf\n", - scale_factor, scale_factor * 1888 + 224, - fwp_optcap, fwp_mincap, fwp_optcap / fwp_mincap - 1, - cap_opt * 1e6, cap_min * 1e6, + fprintf(fp1, "%.3lf, %.1lf, %lf, %lf, %lf, %.3lf, %.3lf, %lf, %lf, %lf\n", + scale_factor, scale_factor * 1888 + 224, + fwp_optcap, fwp_mincap, fwp_optcap / fwp_mincap - 1, + cap_opt * 1e6, cap_min * 1e6, 1 - rsto_RS(I_SUPPLY, cap_opt, t_restore, t_save) / rsto_RS(I_SUPPLY, cap_min, t_restore, t_save), onTimeRatio_RS(I_SUPPLY, cap_opt, T_RESTORE_MIN, T_SAVE_MIN), onTimeRatio_RS(I_SUPPLY, cap_opt, T_RESTORE_MAX, T_SAVE_MAX)); } - printf("\nOutput in .\\results\\rs_to.csv\n"); + printf("\nOutput in rs_to.csv\n"); fclose(fp1); return 0; } - -/* - * How to write this code - * Input: - * Output: - * X - Time overheads (ms) / RAM usage (percentage) / Percentage scaling factor - * Y - Max Fwp, Opt cap, Fwp with min cap, Min cap - * Condition: Supply current? Pick a medium value first. e.g. 400 uA - * - */ \ No newline at end of file diff --git a/model/show_period.c b/model/show_period.c deleted file mode 100644 index 42b1849..0000000 --- a/model/show_period.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "model.h" - -int main(int argv, char** argc) -{ - - double i_supply; - double cap; - - double i_leak; - double i_in; // just for denoting i_harvest - i_leak - double v_pr; - double v_ps; - double t_exe, t_charge; - double t_period; - double t_exe_percent; // 0 ~ 1, ratio of actual active time to total time - - printf("I_supply, Cap, T_period, T_exe, T_exe_ratio, F_out\n"); - // for (i_supply = 0.05e-3; i_supply < 0.92e-3; i_supply += 0.01e-3) { - for (i_supply = 0.0e-3; i_supply < 0.9e-3; i_supply += 0.01e-3) { - // for (cap = 10e-6; cap < 110e-6; cap +=10e-6) { - cap = 43.0e-6; - // i_leak = capCurrentLeak(cap); - i_leak = 0.0; - i_in = i_supply - i_leak; - - if (cap < minCapRisk(i_supply)) { - // printf("Energy insufficient (in worst case, Iin = 0) at Cap = %.0lfuF.\n" - // , cap * 1e6); - return -1.0; // a negative value to indicate insufficient storage - } - - if (i_in < I_SLEEP) t_exe_percent = 0.0; - else if (i_in > I_EXE) t_exe_percent = 1.0; - else{ - -#ifdef HIBERNUS - v_pr = V_R; // no restore after sleep -#else - v_pr = (i_in - I_R) * T_RESTORE / cap + V_R; -#endif // HIBERNUS - - v_ps = (i_in - I_S) * T_SAVE / cap + V_S; - - t_exe = cap * (v_pr - V_S) / (I_EXE - i_in); - t_charge = cap * (V_R - v_ps) / (i_in - I_SLEEP); - -#ifdef HIBERNUS - t_period = t_exe + t_charge + T_SAVE; // no restore after sleep -#else - t_period = t_exe + t_charge + T_SAVE + T_RESTORE; -#endif // HIBERNUS - - t_exe_percent = t_exe / t_period; - printf("%.2lf, %.1lf, %lf, %lf, %lf, %lf\n", i_supply * 1e3, cap * 1e6, t_period, t_exe, t_exe_percent, t_exe_percent * 620); - // printf("%.2lf\n", i_supply * 1e3); - // printf("%lf\n", t_exe_percent * 620); - } - // } - } - - - return 0; -} \ No newline at end of file diff --git a/model/stor_constcurrent.c b/model/stor_constcurrent.c index 798f8be..94c36f5 100644 --- a/model/stor_constcurrent.c +++ b/model/stor_constcurrent.c @@ -1,3 +1,11 @@ +/* + * Copyright (c) 2019-2021, University of Southampton and Contributors. + * All rights reserved. + * + * SPDX-License-Identifier: MIT + */ + + /* * stor_constcurrent.c * @@ -18,33 +26,32 @@ /* ----------- Macros ----------- */ -#define SUBMAX_FACTOR 0.95 // sub-optimal fwp definition +#define SUBMAX_FACTOR 0.95 // sub-optimal fwp definition /* ------ Global Variables ------ */ // capacitance test range int c_min; int c_step; -unsigned int c_no; // number of cap tests incl. c_min +unsigned int c_no; // number of cap tests incl. c_min // supply current test range double i_min; double i_step; -unsigned int i_no; // number of current tests incl. i_min +unsigned int i_no; // number of current tests incl. i_min -/* ------ Function Declare ------ */ -int print_csv(double**, double**, int, int, int); +/* ------ Function Declarations ------ */ +int print_csv(double**, double**, int, int, int); void cap_tolerance(double, double); // results print function tailored to this program /* ----------- Main ------------- */ -int main(int argv, char** argc) -{ +int main(int argv, char** argc) { // two main variables - double cap; // capacitance - double current; // supply current + double cap; // capacitance + double current; // supply current // maximum / optimal values double fwps_max; @@ -58,8 +65,9 @@ int main(int argv, char** argc) int cap_min_int = (int) ceil(minCap() * 1e6); printf("\nMin capacity %lf uF. \n", minCap() * 1e6); printf("Capacity below %d uF is always tested. \n", cap_min_int); - printf("Suggested enter c_min as %d uF to gain a continuous curve. \n\n", cap_min_int); - + printf("Suggested enter c_min as %d uF to gain a continuous curve. \n\n" + , cap_min_int); + // read test ranges of capacitance and current printf("Please enter c_min c_step c_no (int int int, 'uF'): \n"); scanf("%d %d %d", &c_min, &c_step, &c_no); @@ -67,19 +75,20 @@ int main(int argv, char** argc) scanf("%lf %lf %d", &i_min, &i_step, &i_no); // allocate memory for storing resutls - // table for data with integral capacitance + // table for data with integral capacitance double **table; table = (double **) calloc(i_no, sizeof(double *)); for (int i = 0; i < i_no; i++) { table[i] = (double *) calloc(c_no, sizeof(double)); } - + // table for data below the minimum storage capacity double **table_small_cap; - table_small_cap = (double **) calloc(i_no + 1, sizeof(double *)); // one more column to store current values + // one more column to store current values + table_small_cap = (double **) calloc(i_no + 1, sizeof(double *)); for (int i = 0; i < i_no + 1; i++) { - // take three points equally between minCapRisk and minCap + // take three points equally between minCapRisk and minCap table_small_cap[i] = (double *) calloc(cap_min_int * 10, sizeof(double)); } @@ -88,50 +97,56 @@ int main(int argv, char** argc) // csv file to store those maximum / optimal values FILE* fp1 = NULL; - if ((fp1 = fopen("results\\stor_constcurrent_maxfwps.csv", "w")) == NULL) { + if ((fp1 = fopen("stor_constcurrent_maxfwps.csv", "w")) == NULL) { printf("Failed to write file stor_constcurrent_maxfwps.csv.\n"); return 1; } fprintf(fp1, "current(mA),fwps_impr_max,cap_max,cap_submax,mincaprisk(uF)\n"); - + printf("\nCapacitance tolerance effect:\n"); + printf("Current (A), Optimal Cap (uF), +20%%Cap (progress change), -20%%Cap (progress change)\n"); for (int j = 0; j < i_no; j++) { - current = (i_min + j * i_step) * 1e-3; + // small cap (< minCap) test for (int i = 0; i < cap_min_int * 10; i++) { - cap = i * 1e-7; + cap = i * 1e-7; // cap = ie-1 uF // cap = minCapRisk(current) * - // (NO_SMALL_CAP - i) / + // (NO_SMALL_CAP - i) / // (double) NO_SMALL_CAP + // minCap() * // i / (double) NO_SMALL_CAP; + + // last row of table_small_cap[][] stores capacitance values if (j == 0) table_small_cap[i_no][i] = cap; table_small_cap[j][i] = onTimeRatio(current, cap); - if (fabs(table_small_cap[j][i] + 1.0) <= 1e-15) table_small_cap[j][i] = 0.0; // detect -1.0 - }; + // detect -1.0, which indicates insufficient capacitance + if (fabs(table_small_cap[j][i] + 1.0) <= 1e-15) + table_small_cap[j][i] = 0.0; + } - // int cap test + // int cap (> minCap) test for (int i = 0; i < c_no; i++) { - cap = (c_min + i * c_step) * 1e-6; // c = i uF - + cap = (c_min + i * c_step) * 1e-6; // cap = i uF + table[j][i] = onTimeRatio(current, cap); - // Here we use the actual active time percentage - // to denote forward progressing speed. - // A -1 return value represents a cap that smaller - // than the safe minimum capacity. + // Here we use the actual active time percentage + // to denote forward progressing speed. + // A -1 return value represents a cap that smaller + // than the safe minimum capacity. - if (fabs(table[j][i] + 1.0) <= 1e-15) table[j][i] = 0.0; + if (fabs(table[j][i] + 1.0) <= 1e-15) + table[j][i] = 0.0; // find cap_max if (i == 0) { fwps_max = table[j][i]; cap_max = i; - } - else { // 0 < i < c_no + } else { + // 0 < i < c_no if (table[j][i] > fwps_max) { fwps_max = table[j][i]; cap_max = i; @@ -144,23 +159,26 @@ int main(int argv, char** argc) // find sub max cap_submax = 0; - while (table[j][cap_submax] / onTimeRatio(current, minCap()) - 1 - < SUBMAX_FACTOR * (fwps_max / onTimeRatio(current, minCap()) - 1)) + while (table[j][cap_submax] / onTimeRatio(current, minCap()) - 1 + < SUBMAX_FACTOR * (fwps_max / onTimeRatio(current, minCap()) - 1)) cap_submax++; cap_submax = c_min + cap_submax * c_step; fprintf(fp1, "%.2f, %.6lf, %d, %d, %lf\n", - i_min + j * i_step, fwps_max / onTimeRatio(current, minCap()) - 1, cap_max, cap_submax, minCapRisk(current) * 1e6); + i_min + j * i_step, fwps_max / onTimeRatio(current, minCap()) - 1, + cap_max, cap_submax, minCapRisk(current) * 1e6); } // print results - if (print_csv(table, table_small_cap, c_no, i_no, cap_min_int * 10) == 1) + if (print_csv(table, table_small_cap, c_no, i_no, cap_min_int * 10) == 1) printf("Failed to write file stor_constcurrent.csv.\n"); fclose(fp1); + printf("See more results in 'stor_constcurrent.csv' and 'stor_constcurrent_maxfwps.csv'.\n"); + return 0; } @@ -168,11 +186,10 @@ int main(int argv, char** argc) * print out results to a csv file * c_min and c_step are used to determine row headings */ -int print_csv(double **table, double **table_small_cap, int row, int col, int no_cap_small) -{ +int print_csv(double **table, double **table_small_cap, int row, int col, int no_cap_small) { // store FILE* fp2 = NULL; - if ((fp2 = fopen("results\\stor_constcurrent.csv", "w")) == NULL) { + if ((fp2 = fopen("stor_constcurrent.csv", "w")) == NULL) { return 1; } @@ -186,16 +203,16 @@ int print_csv(double **table, double **table_small_cap, int row, int col, int no for (int i = 0; i < no_cap_small; i++) { // print values fprintf(fp2, "%.1lf", table_small_cap[i_no][i] * 1e6); - for (int j = 0; j < col; j++) + for (int j = 0; j < col; j++) fprintf(fp2, ",%.6lf", table_small_cap[j][i]); fprintf(fp2, "\n"); } for (int i = 0; i < row; i++) { - // print row headings + // print row headings fprintf(fp2, "%d", c_min + i * c_step); // print values - for (int j = 0; j < col; j++) + for (int j = 0; j < col; j++) fprintf(fp2, ",%.6lf", table[j][i]); fprintf(fp2, "\n"); } @@ -204,16 +221,15 @@ int print_csv(double **table, double **table_small_cap, int row, int col, int no return 0; } -void cap_tolerance(double current, double cap) -{ +void cap_tolerance(double current, double cap) { double fwpg = onTimeRatio(current, cap); double fwpg_p20 = onTimeRatio(current, cap * 1.2); double fwpg_m20 = onTimeRatio(current, cap * 0.8); - - printf("%lf, %.1lf, %.1lf (%lf), %.1lf (%lf)\n", - current, cap * 1e6, - cap * 1.2e6, - fwpg_p20 / fwpg - 1, - cap * 0.8e6, + + printf("%lf, %.1lf, %.1lf (%lf), %.1lf (%lf)\n", + current, cap * 1e6, + cap * 1.2e6, + fwpg_p20 / fwpg - 1, + cap * 0.8e6, fwpg_m20 / fwpg - 1); -} \ No newline at end of file +} -- GitLab