FEMM/ffi/femm_curr.cpp

125 lines
4.0 KiB
C++

// current-flow FFI body: opaque doc, pipeline, mesh accessors. delegates to csolv's CFemmeDocCore.
#include "../csolv/StdAfx.h"
#include "../csolv/CSOLVDLG.H"
#include "../csolv/complex.h"
#include "../csolv/mesh.h"
#include "../csolv/spars.h"
#include "../csolv/femmedoccore.h"
#include "femm_curr.h"
#include <cstdio>
#include <cstdarg>
#include <string>
// stub view: math files reference TheView globally, math methods call SetPos/SetDlgItemText/InvalidateRect on it.
static CcsolvDlg s_stub_view;
CcsolvDlg* TheView = &s_stub_view;
// math files declare and call these for error reporting.
int MsgBox(const char* fmt, ...) {
va_list ap; va_start(ap, fmt);
std::vfprintf(stderr, fmt, ap);
std::fputc('\n', stderr);
va_end(ap);
return 0;
}
int MsgBox(const std::string& s) {
std::fprintf(stderr, "%s\n", s.c_str());
return 0;
}
// referenced by csolv/main.cpp's old_main wait loop; main.cpp itself is not linked here.
inline bool IsWindow(void*) { return true; }
struct FemmCurrDoc {
CFemmeDocCore doc;
FemmCurrProgressFn cb = nullptr;
void* user = nullptr;
std::string path_buf;
};
extern "C" {
FemmCurrDoc* femm_curr_doc_new(void) {
auto* d = new FemmCurrDoc();
d->doc.TheView = &s_stub_view;
return d;
}
void femm_curr_doc_free(FemmCurrDoc* d) {
delete d;
}
void femm_curr_doc_set_progress(FemmCurrDoc* d, FemmCurrProgressFn fn, void* user) {
if (!d) return;
d->cb = fn;
d->user = user;
}
int femm_curr_doc_load_fec(FemmCurrDoc* d, const char* path) {
if (!d || !path) return 0;
d->path_buf = path;
d->doc.PathName = const_cast<char*>(d->path_buf.c_str());
return d->doc.OnOpenDocument() ? 1 : 0;
}
int femm_curr_doc_load_mesh(FemmCurrDoc* d) {
return (d && d->doc.LoadMesh()) ? 1 : 0;
}
int femm_curr_doc_renumber(FemmCurrDoc* d) {
return (d && d->doc.Cuthill()) ? 1 : 0;
}
// allocates a CBigComplexLinProb and runs AnalyzeProblem + WriteResults.
int femm_curr_doc_solve(FemmCurrDoc* d) {
if (!d) return 0;
CBigComplexLinProb L;
L.TheView = &s_stub_view;
L.Precision = d->doc.Precision;
if (!L.Create(d->doc.NumNodes + d->doc.NumCircProps, d->doc.BandWidth, d->doc.NumNodes)) return 0;
if (!d->doc.AnalyzeProblem(L)) return 0;
if (!d->doc.WriteResults(L)) return 0;
return 1;
}
int femm_curr_doc_write_results(FemmCurrDoc* /*d*/, const char* /*out_path*/) {
// results currently emitted inline by solve(); reserved hook for explicit output redirection.
return 1;
}
double femm_curr_doc_frequency (const FemmCurrDoc* d) { return d ? d->doc.Frequency : 0.0; }
int femm_curr_doc_axisymmetric (const FemmCurrDoc* d) { return (d && d->doc.ProblemType) ? 1 : 0; }
double femm_curr_doc_depth (const FemmCurrDoc* d) { return d ? d->doc.Depth : 0.0; }
double femm_curr_doc_precision (const FemmCurrDoc* d) { return d ? d->doc.Precision : 0.0; }
int femm_curr_doc_num_nodes (const FemmCurrDoc* d) { return d ? d->doc.NumNodes : 0; }
void femm_curr_doc_node (const FemmCurrDoc* d, int i, double* x, double* y) {
if (!d || !d->doc.meshnode) return;
if (x) *x = d->doc.meshnode[i].x;
if (y) *y = d->doc.meshnode[i].y;
}
int femm_curr_doc_num_elements (const FemmCurrDoc* d) { return d ? d->doc.NumEls : 0; }
void femm_curr_doc_element (const FemmCurrDoc* d, int i, int* p0, int* p1, int* p2) {
if (!d || !d->doc.meshele) return;
if (p0) *p0 = d->doc.meshele[i].p[0];
if (p1) *p1 = d->doc.meshele[i].p[1];
if (p2) *p2 = d->doc.meshele[i].p[2];
}
int femm_curr_doc_num_materials (const FemmCurrDoc* d) { return d ? d->doc.NumBlockProps : 0; }
int femm_curr_doc_num_boundaries (const FemmCurrDoc* d) { return d ? d->doc.NumLineProps : 0; }
int femm_curr_doc_num_conductors (const FemmCurrDoc* d) { return d ? d->doc.NumCircProps : 0; }
// field sampling is post-processor territory; not exposed by the solver alone.
double femm_curr_doc_field_at (const FemmCurrDoc* /*d*/, double /*x*/, double /*y*/, FemmCurrField /*c*/) {
return 0.0;
}
} // extern "C"