/* * Copyright (C) 2022 NHR@FAU, University Erlangen-Nuremberg. * All rights reserved. This file is part of nusif-solver. * Use of this source code is governed by a MIT style * license that can be found in the LICENSE file. */ #include #include #include #include #include "trace.h" #define U(i, j) u[(j) * (imax + 2) + (i)] #define V(i, j) v[(j) * (imax + 2) + (i)] static int ts = 0; static void printState(Tracing* t) { printf("Cursor: %d Total particles: %d\n", t->cursor, t->totalParticles); } static void advanceParticles( Tracing* t, double delt, double* restrict u, double* restrict v) { double delx = t->grid.dx; double dely = t->grid.dy; double* m = t->memorypool; int* p = t->particles; int imax = t->grid.imax; int jmax = t->grid.jmax; for (int i = 0; i < t->totalParticles; i++) { int particleId = p[i]; double x = m[particleId * NCOORD + X]; double y = m[particleId * NCOORD + Y]; // printf("P%d - X %f Y %f\n", i, x, y); // Interpolate U int iCoord = (int)(x / delx) + 1; int jCoord = (int)((y + 0.5 * dely) / dely) + 1; double x1 = (double)(iCoord - 1) * delx; double y1 = ((double)(jCoord - 1) - 0.5) * dely; double x2 = (double)iCoord * delx; double y2 = ((double)jCoord - 0.5) * dely; // printf("U - iCoord %d jCoord %d\n", iCoord, jCoord); double un = (1.0 / (delx * dely)) * ((x2 - x) * (y2 - y) * U(iCoord - 1, jCoord - 1) + (x - x1) * (y2 - y) * U(iCoord, jCoord - 1) + (x2 - x) * (y - y1) * U(iCoord - 1, jCoord) + (x - x1) * (y - y1) * U(iCoord, jCoord)); double xn = x + delt * un; m[particleId * NCOORD + X] = xn; // Interpolate V iCoord = (int)((x + 0.5 * delx) / delx) + 1; jCoord = (int)(y / dely) + 1; x1 = ((double)(iCoord - 1) - 0.5) * delx; y1 = (double)(jCoord - 1) * dely; x2 = ((double)iCoord - 0.5) * delx; y2 = (double)jCoord * dely; // printf("V - iCoord %d jCoord %d\n", iCoord, jCoord); double vn = (1.0 / (delx * dely)) * ((x2 - x) * (y2 - y) * V(iCoord - 1, jCoord - 1) + (x - x1) * (y2 - y) * V(iCoord, jCoord - 1) + (x2 - x) * (y - y1) * V(iCoord - 1, jCoord) + (x - x1) * (y - y1) * V(iCoord, jCoord)); double yn = y + delt * vn; m[particleId * NCOORD + Y] = yn; } double xlength = t->grid.xlength; double ylength = t->grid.ylength; int cntNew = 0; int tmp[t->totalParticles]; // Check for particles to remove for (int i = 0; i < t->totalParticles; i++) { int particleId = p[i]; double x = m[particleId * NCOORD + X]; double y = m[particleId * NCOORD + Y]; if (!((x < 0.0) || (x > xlength) || (y < 0.0) || (y > ylength))) { tmp[cntNew++] = i; } } t->totalParticles = cntNew; memcpy(t->particles, tmp, cntNew * sizeof(int)); } static void injectParticles(Tracing* t) { double* line = t->line; double* m = t->memorypool; for (int i = 0; i < t->numParticles; i++) { t->particles[t->totalParticles] = t->cursor; m[(t->cursor) * NCOORD + X] = line[i * NCOORD + X]; m[(t->cursor) * NCOORD + Y] = line[i * NCOORD + Y]; t->cursor++; t->totalParticles++; } } static void writeParticles(Tracing* t) { FILE* fp; double* m = t->memorypool; int* p = t->particles; char filename[50]; snprintf(filename, 50, "particles_%d.dat", ts++); fp = fopen(filename, "w"); if (fp == NULL) { printf("Error!\n"); exit(EXIT_FAILURE); } for (int i = 0; i < t->totalParticles; i++) { int particleId = p[i]; double x = m[particleId * NCOORD + X]; double y = m[particleId * NCOORD + Y]; fprintf(fp, "%f %f\n", x, y); } fclose(fp); } void trace(Tracing* t, double* restrict u, double* restrict v, double time) { if (time >= t->traceStart) { if ((time - t->lastUpdate[INJECT]) > t->traceInject) { injectParticles(t); t->lastUpdate[INJECT] = time; } if ((time - t->lastUpdate[WRITE]) > t->traceWrite) { writeParticles(t); t->lastUpdate[WRITE] = time; } advanceParticles(t, time - t->lastUpdate[ADVANCE], u, v); t->lastUpdate[ADVANCE] = time; } } void initTrace(Tracing* t, Parameter* p) { size_t numParticles = p->nparticles; size_t totalParticles = (size_t)(p->te - p->traceStart) / (size_t)p->traceInject; totalParticles += 2; totalParticles *= numParticles; double x1 = p->lineX1; double y1 = p->lineY1; double x2 = p->lineX2; double y2 = p->lineY2; for (int i = 0; i < NUMTIMERS; i++) { t->lastUpdate[i] = p->traceStart; } t->grid.imax = p->imax; t->grid.jmax = p->jmax; t->grid.xlength = p->xlength; t->grid.ylength = p->ylength; t->grid.dx = p->xlength / p->imax; t->grid.dy = p->ylength / p->jmax; t->numParticles = numParticles; t->totalParticles = 0; t->cursor = 0; t->traceStart = p->traceStart; t->traceWrite = p->traceWrite; t->traceInject = p->traceInject; t->particles = (int*)malloc(totalParticles * sizeof(int)); t->memorypool = (double*)malloc(totalParticles * NCOORD * sizeof(double)); t->line = (double*)malloc(numParticles * NCOORD * sizeof(double)); double* line = t->line; for (int i = 0; i < numParticles; i++) { double spacing = (double)i / (double)(numParticles - 1); double x = spacing * x1 + (1.0 - spacing) * x2; double y = spacing * y1 + (1.0 - spacing) * y2; //printf("S: %f x: %f y: %f\n", spacing, x, y); line[i * NCOORD + X] = x; line[i * NCOORD + Y] = y; } } void freeTrace(Tracing* t) { free(t->line); }